关于javascript:用TodoList实例告诉你怎么在项目中使用TypeScript

29次阅读

共计 3752 个字符,预计需要花费 10 分钟才能阅读完成。

为什么用 todolist

古代的框架教程目前再也不是写个 hello world 那么简略了,而是须要有肯定根底能力可能做到数据绑定、遍历、条件判断等各种逻辑,而能实现这一系列内容的,todolist 就是个很好的实现,比方 react 的教程、solijs 教程都是以 todolist 为例

当然,你如果想看各种框架实现 todolist 的话,你能够拜访 TodoMVC【https://todomvc.com/】,这外面展现了各种框架如何实现了 todolist

todolist 的 ts 化

然而对于 ts 教程来说,只有官网的一些实例,并没有一个很好的我的项目上的教程,也就是无关实战的局部,很多同学在学习了 ts 之后,只会一些根底的 js 类型的设置,放在我的项目中就不分明了,所以咱们就出了这个教程

当然在开始之前,咱们要理解这个教程不依赖任何的前端库,比方 react,vue 等,同时也为了节省时间,咱们仅仅是放出一些要害的 ts 代码,不须要将整个利用都展现进去,同样可能让你晓得 ts 的应用

数据到视图

一个 tudolist 对应的数据是怎么样的?就拿方才的视图来看的话,它应该是一个对象数组,数据应该是这样的

[
  {
    id: 1,
    text: '待办事项 1',
    done: false
  },
  {
    id: 2,
    text: '待办事项 2',
    done: false
  },
  {
    id: 3,
    text: '待办事项 3',
    done: false
  }
]

其中 id 是每一个代办事项的惟一标识,text 是事项名称,done 示意是否实现

当咱们点击实现的时候,实际上就是每一项的 done 产生了变动,数据发生变化之后驱动咱们的视图做出对应的扭转

实现 handleTodoItem

对应的上述的点击事件,咱们实现一下它的伪代码,当其点击的时候,须要解决对应的数据,先应用 js 实现

function handleTodoItem(todo){
  // 点击的时候 todo 中的 done 的布尔值取反
  return {
    ...todo,
    done: !todo.done
  }
}

而后咱们应用 ts 进行优化

type Todo = {
  id: number;
  text: string;
  done: boolean;
}
// 如果某个变量是 todo 类型,能够这样
const todoItem: Todo = {
  id: 1,
  text: '待办事项 1',
  done: false
}

这样 ts 类型就是失常的,如果相应的 todoItem 不匹配,则编译就会产生谬误,能够让谬误提前感知,并且如果我的项目中有配置的 ts 相干,vscode 中就会给出对应的错误信息

对应到 handleTodoItem 这个办法中,应该怎么写呢?

function handleTodoItem(todo: Todo): Todo {// 逻辑实现}

readonly

对于 handleTodoItem 这个函数来说,函数应该是无副作用的,所以传进去的 todo 对象,不应该发生变化,而是返回一个新的对象

比方这种办法,尽管可能实现同样的内容,然而它是有副作用的,扭转了传入的参数,是不可取的

function handleTodoItem(todo: Todo):Todo {
  // 点击的时候 todo 中的 done 的布尔值取反
  todo.done = !todo.done
  return todo
}

然而这种的 ts 并不会报错,怎么办?那就须要借助咱们的 ts 进行类型校验,你能够这样

type Todo = {
  readonly id: number;
  readonly text: string;
  readonly done: boolean;
}

当你尝试批改批改的话,就会产生 ts 谬误,不容许批改,因为 Todo 类型是只读的,当然你也能够这样设置对象中所有的属性为只读

type Todo = Readonly<{
  id: number;
  text: string;
  done: boolean;
}>

在 ts 中,这种 Readonly 的关键词还有很多,比方 Required,Partial 等,如有须要,大家可自行搜寻

分类

对于曾经实现的 list,咱们须要将其进行分类筛选,比方咱们要筛选出所有曾经实现的我的项目,那么体现就是一个数组,并且 done 为 true

[
  {
    id: 1,
    text: '待办事项 1',
    done: true
  },
  {
    id: 2,
    text: '待办事项 2',
    done: true
  }
]

如何示意一个数组类内容呢?Todo[]这种形式就能示意上述数据,同样的,函数的参数是不容许批改的,防止副作用,所以能够这样

function completeTodoList(todos: readonly Todo[]
): Todo[] {// ...}

当然,因为 Todo 的 type 中的 done 为 boolean,然而在 completeTodoList 中 done 的值为 true,所以咱们须要从新定义一个类型

type CompletedTodo = Readonly<{
  id: number;
  text: string;
  done: true;
}>

所以上述的办法就会变成

function completeTodoList(todos: readonly Todo[]
): CompletedTodo[] {// ...}

穿插类型

对于下面的 Todo 和 CompletedTodo 类型,其中这两个类型的 id 和 text 都是反复的,咱们能够删除反复的逻辑,应用穿插类型

举个例子

type A = {a: number}
type B = {b: string}

type AandB = A & B

// 后果为
// {
//   a: number
//   b: string
// }

当两个类型 key 雷同时,第二个 key 会笼罩掉第一个的内容

type A = {key: number}
type B = {key: string}

type AandB = A & B

// 后果为
// {
//   key: string
// }

那针对 Todo 和 CompletedTodo 类型,咱们想从 Todo 通过穿插类型失去 CompletedTodo,该怎么做呢?

type CompletedTodo = Todo & {readonly done: true}

是不是很简洁,并且去除了一些反复代码

新增性能

如果在 Todo 的根底上,咱们新增了一个性能,对应的 todo 的优先级,应用 priority 这个字段示意

并且一共有三种优先级

  • !!!
  • !!

你能够 priority: 2 这样设置,展现为【!!】当然你也能够自定义,比方

{
  priority: {custom: '紧急'}
}

则展现为【紧急】,所以这时候数据变成了

[
  {
    id: 1,
    text: '待办事项 1',
    done: false,
    priority: 1
  },
  {
    id: 2,
    text: '待办事项 2',
    done: false,
    priority: 2
  },
  {
    id: 3,
    text: '待办事项 3',
    done: false,
    priority: {custom: '紧急'}
  },
  {
    id: 4,
    text: '待办事项 4',
    done: false
  },
]

咱们曾经有了 Todo 类型,如何新增一个 key 呢?

联结类型

下面咱们之后穿插类型通过 & 连贯,那联结类型则是通过 | 连贯,同样的举个例子

type Foo = number | string;

这示意 Foo 类型能够是一个数字,也能够是一个 string 类型,所以咱们的 priority 类型能够这样设置

type Priority = 1 | 2 | 3 | {custom: string};

这个时候 priority 就是咱们想要的内容了,所以 todo 的类型能够变一下

type Todo = Readonly<{
  id: number;
  text: string;
  done: boolean;
  priority: Priority;
}>

可选属性

下面的 priority 这个属性目前是必填的,然而这个属性咱们能够不写,也就是 todo 能够没有优先级,针对这种状况,咱们能够应用可选属性

type Todo = Readonly<{
  id: number;
  text: string;
  done: boolean;
  priority?: Priority;
}>

在对应的中央增加一个? 即可

数据转视图

那对应的 priority 的数据有了,如何把 1,2,3 这种的转成!!!的模式呢?

能够自定义一个函数,也就是 priorityToString

priorityToString(1)
//!priorityToString(2)
//!!priorityToString(3)
//!!!priorityToString({custom: '紧急'})
// 紧急

状况比拟少,可能你会这样写

function priorityToString(priority: Priority): string {if(priority === 1){return '!'}else if(priority === 2){return '!!'}else if(priority === 3){return '!!!'}else{return priority.custom}
}

联结类型咱们通过 if 条件进行判断的时候,它会主动确认每个 if 条件下的参数类型,这也是联结类型的弱小之处

总结

基本上咱们我的项目中用到的一些知识点这里都概括了,通过一个简略的我的项目,将 ts 的一些根本类型给大家做了一个简要的阐明,如果你有更多疑难,或者我的项目中的问题,欢送关注公众号【FE 情报局】留言,我会尽可能帮忙你解决问题

参考:https://ts.chibicode.com/todo/

正文完
 0