Vue3+ts实现(ToDo)

242 阅读5分钟

1. 基础配置(vite版本)

第一步配置 ![[Pasted image 20221030232813.png]]

Pasted image 20221030232813.png

  • 第二步配置(告诉vue单文件 @路径) ![[Pasted image 20221030233235.png]]

Pasted image 20221030233235.png

2.拆分组件

  • 拆分组件
  • 引入组件到App组件中
  • 使用组件 ![[Pasted image 20221030234210.png]]

Pasted image 20221030234210.png

3.动态页面(初始化动态数据)

1.在App组件使用ref定义动态数据

  • 引入ref
  • 使用ref定义数据 这样的数据具有响应式
import {ref} from 'vue'
const todolist = ref([
    {id:1,count:'抽烟',isOver:false},  //是否选中?
    {id:1,count:'喝酒',isOver:true},
    {id:1,count:'烫头',isOver:false}
])

2.传递数据到Main组件

App.vue

<Main :todolist="todolist"></Main>

Main.vue

  • 通过props接收*
//遍历数据
 <Item v-for="(item,index) in todolist" :key="index"></Item>
//在模板中操作数据  可以直接写
//在ts代码逻辑中需要  props.xxxx
const props = defineProps(['todolist'])

3.定义数据类型(做类型限制)

  • 定义的是对象类型,用interface
  • 定义复合类型 一般用type >1.定义数据类型 ![[Pasted image 20221101093137.png]]

Pasted image 20221101093137.png

2.子组件接收数据(对数据进行类型限定) ![[Pasted image 20221101094417.png]]

Pasted image 20221101094417.png

//接收数据,进行类型限定
//1.原始写法
interface PropsData{  //定义接口
    todoList : TodolistData
}
const props = defineProps<TodolistData>()
//2.进阶写法
const props = defineProps<{
    todoList:todoListData
}>()

3.将数据传递到各组件

  • App=> Main ![[Pasted image 20221102095338.png]]

Pasted image 20221102095338.png

  • Main=> Item ![[Pasted image 20221102095620.png]]

Pasted image 20221102095620.png

  • App =>Footer* ![[Pasted image 20221102100017.png]]

Pasted image 20221102100017.png

4.Footer 组件中

  • 通过计算属性 计算出 全部的数量 已完成的数量
//使用计算属性  计算
const overNum = computed(()=>{
  return props.todoList.reduce((prev:number,item:TodoData)=>{
    if (item.isOver){//计算  已完成  如果被选中就是 已完成
      prev +=1
    }
    return prev
  },0) 
  • 通过计算属性计算属性 计算出是否全选
//使用计算属性  计算是否全选  可读可写传递的是对象
const isCheckAll = computed({
  get(){//这里  类型都是  布尔值  ts是强类型  和之前无关
    return props.todoList.every(item=>item.isOver)  && props.todoList.length > 0 //数组方法 要是声明类型  就得加括号
  },
  set(){}
})

4.交互之添加 todo

1.收集数据

  • 定义ref数据 通过v-model双向绑定实时收集数据
    • 判断输入的类型是否为空
//紧接着 我们就要判断 传入的数据是否是空的
const addT = () =>{
  if(content.value && content.value.trim()){ 
//此处的字符串trim方法去除两侧空格,如果为空 去除空格后就是空的
    let obj = {
      id:Date.now(),
      content:content.value,
      isOver:false
    }
  }
}

2.回车事件

* 输入内容  按下回车之后添加到列表里面
    * 通过回车事件 来搞定这一步操作
//接收定义好的函数  确定它的类型
const props = defineProps<{
    addTodo(todo:TodoData):void,  //接收函数以及定义它的类型
    //addTodo:()=>void
}>()

const addT = () =>{
  if(content.value && content.value.trim()){ 
//此处的字符串trim方法去除两侧空格,如果为空 去除空格后就是空的
    let obj = {
      id:Date.now(),
      content:content.value,
      isOver:false
    }
  }
//把定义好的 数据类型 在传回父组件
props.addTodo(obj)
}

3.总结逻辑

  • 输入 回车 显示而且添加在最前面
  • 首先 收集数据 : 你输进去的收集到
  • 判断输入的是否为空
    • 如果是空的 报错
    • 如果不是空的 把它添加到列表里面 (定义添加进去的类型 )*
  • 按下回车 数据会添加到 列表的最前面
    • 要添加的数据类型 要通过props 拿到*
    • 再把要添加的数据类型 传到父组件

注意 : header中通过props 拿到 addtodo 这个函数, 此时我们已经定义好数据obj传参,通过 props.addtodo(obj) 调用这个函数
实现 添加功能
本质就是一个通过传参改变属性的过程

5.交互之删除高亮

1.删除原来的

  • 删掉原来的样式
  • 删掉原来的css*

2.给删除按钮设置 v-show

  • 定义isshow 为ref响应式数据 放false*

3.给li绑定移入移出事件

  • @mouseenter="isShow=true" @mouseleave="isShow=false"*

4.给li设置高亮样式

强制绑定 class css &.active {  background-color: hotpink;} js :class="{ active: isShow }"

6.交互之修改单选框

核心就是 通过在下标 修改单选框是否被选中 各组件之间传递的就是 下标

1.点击事件

  • 设置点击事件 定义函数 updataT

2.传递参数index

把下标index(item)=>(main)=>(app) 组件之间传递 最后修改isOver

  • 我们需要下标 就得传递过来 通过props拿到这个函数 同时他携带参数index(下标)
  • 在定义的点击事件中 props.updateOneTodo(props.index)
    • 通过调用函数 把下标传进去 传到父组件(main)中* * 且在main组件中定义函数类型 *updataone():void updataoentodo:()=>void ![[Pasted image 20221102100813.png]]

Pasted image 20221102100813.png

  • 后面操作都与其类似 顾不细说明*

7.删除操作

  • 把下标index(item)=>(main)=>(app) 组件之间传递
  • 也是通过传递参数 index 通过删除index 删除这个数据*
  • 一层一层传递*

8.全选全不选

  • v-model 双向数据绑定 对这一项操作之后 遍历每一项 让每一项操作一样*
    • 或选中或不选中
    • 得通过计算属性 算出来的
    • 通过set去修改 计算出新的属性
    • 接收函数 传递参数* ![[Pasted image 20221102101503.png]]

Pasted image 20221102101503.png

9.清除已完成

![[Pasted image 20221102101224.png]]

Pasted image 20221102101224.png

10.本地化存储

  • 需要去用watch监视 是否发生变化 一旦变化就把变化的数据存储起来
  • 这里的数据是数组类型 所以要深度监视 ![[Pasted image 20221102094010.png]]

Pasted image 20221102094010.png

11.总结

  • 1、数据在哪,修改数据的方法就在哪
  • 2、数据从父组件传递给子组件,无论传递的是基本值还是对象地址,都是让子组件去使用的,而不是让你去修改的
  • 3、props接收到的数据相当于是子组件data当中的数据
  • 但是最大的区别就是data的数据,子组件可以随意改 而父组件传递过来的数据,不能在子组件修改,如果非要对传递过来的数据进行修改 那么可以根据传递过来的数据,计算自己的一份数据,然后可以修改,修改的时候修改的是自己计算的属性数据 在计算的属性数据当中set,里面也不能直接操作传递过来的数据,得调用传过来的方法去修改