• ToDoList待办事件(Vue实现)详解


    组件化的编码流程(通用)

    1. 实现静态组件:抽取组件,使用组件实现静态页面效果
    2. 展示动态数据
      数据的类型名称
      数据保存的组件位置
    3. 交互-从绑定事件监听开始

    实现静态页面

    组件按照功能划分

    也可以按照其他的划分,我是按照功能划分的

    制作过程

    创建文件夹,终端进入目录下创建项目

    vue create todolist
    
    • 1

    在这里插入图片描述

    在组件文件夹下创建四个文件,分别是MyTop.vue;List.vue;Item.vue;MyFooter.vue;
    并将四个组件引入App.vue
    注意:Top.vue不要写Header.vue,容易和html的标签冲突
    后来我的Top.vue也报错了,我改长一点,MyTop,就正常了
    注册组件

    export default {
      name: 'App',
      components: { MyTop,MyList,MyFooter}
    }
    
    • 1
    • 2
    • 3
    • 4

    因为item是list的子组件所以item注册在list里面就好啦
    在这里插入图片描述

    完整代码

    MyTop.vue

    
    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    MyList.vue

    
    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    MyItem.vue

    
    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    MyFooter.vue

    
    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    App.vue

    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    展示动态数据

    待办事件的数据需要数组来进行存储,id标识,数组保存在List.
    在MyList中的MyItem子组件中遍历todos数组,给MyItem传数据。
    在MyItem中设置props设置传值

       //声明接收todo对象
        props:['todo'],
    
    • 1
    • 2

    checkbox添加checked就会在页面中显示勾选,动态的拥有某个属性,

    :checked="true"
    
    • 1

    在表达式通过改变true来实现是否勾选
    使其=todo.done即可

    完整代码

    MyItem.vue

    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    MyList.vue

    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    添加待办事件

    在Top中将用户的输入包装成一个todo对象,将用户的输入todoObj添加到list当中
    两个兄弟组件之间传递数据的思路:父组件App中有todos数组(将list中的数据复制到app中),将top中的todoObj传给todos,再通过props将todos中的数据传给list。

    App.vue

     
      
    
    • 1
    • 2
    
      
    
    • 1
    • 2

    MyTop

     props:['addTodo'],
    
    • 1

    子组件给父组件传数据的思路

    父组件传给子组件一个函数,子组件合适的时候调用。

    top传给list数据的整个过程

    App中操作todos中的数据unshift可以捕获到数组的修改,todos改变,vue重新解析模板,此时todos增加一个数据,todo数组传给mylist,mylist会重新解析模板,myitem出现四个虚拟dom,dom比较,旧的复用,新的添加。

    完善细节

    回车键后输入框为空

      e.target.value=''
    
    • 1

    但是这个语句直接操作DOM了,违背了Vue的原则。


    input框添加v-model可以避免这个问题
    在这里插入图片描述

    //在methods里面添加

    this.title=''
    
    • 1

    输入空格回车也会成功添加

      if (!this.title.trim()) return alert('输入不能为空')
    
    • 1

    勾选

    勾选与否引起数据的变化,才可以显示完成率,产生交互.

    通过勾选找到数据的id,在todo里面找到,然后通知app组件将对应的todo对象的done值取反。

    首先需要input框显示勾选的todo(初始化交互)

    :checked="todo.done"
    
    • 1

    绑定事件响应是否勾选(click/change都可以)

    @click="handleCheck(todo.id)
    
    • 1

    可以通过点击输出勾选事件的id

    console.log(id)
    
    • 1

    app组件中,通知app组件将对应的todo对象的done值取反

        checkTodo(id) {
          // 遍历list中的item
          this.todos.forEach((todo) => {
            if (todo.id === id) todo.done=!todo.done
          })
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    组件间通信
    本次采用逐次传递。
    在App中将checkTodo传递给MyList组件,在MyList组件中使用props接收checkTodo

          
    
    • 1
      props:['todos','checkTodo'],
    
    • 1

    因为是Myitem使用,所以在MyList组件中的MyItem中单项数据绑定

    :checkTodo="checkTodo"
    
    • 1

    在MyItem中使用props接收checkTodo。

    MyItem中input框使用v-model双向数据绑定v-model=“todo.done”,通过布尔值决定input的checkbox是否勾选
    props传值todo,todo的属性值修改,vue监测的就是todo属性
    但是props的值不允许修改
    看一下下面的例子

    let a=3;
    a=8;
    
    • 1
    • 2

    修改了

    let obj={a:2,b:3}
    obj.=666
    obj={x:100,y:200}
    
    • 1
    • 2
    • 3

    vue只能监测到obj={x:100,y:200}。

    在本项目中myItem中添加

     
    
    • 1

    props接收a
    但是这种方法并不推荐,因为有点违反原则,修改了props,vue监测不到。

    删除

    在item中给按钮button添加点击事件handleDelete,注意接受todo的id

     
    
    • 1
     handleDelete(id) {
          // 删除
          if (confirm('确定删除吗?')) {
            // console.log(id)
            
          }
          
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
        deleteTodo(id) {
          this.todos = this.todos.filter((todo) => {
            return todo.id!==id
          })
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    再次经历爷孙传值

    先App传给MyList,MyList中props接收deleteTodo,MyItem标签中单项数据绑定deleteTodo。之后MyList传给MyItem,item的props接收即可。

       
    
    • 1

    myitem中的操作
      props: ['todo', 'checkTodo','deleteTodo'],
    
    • 1
        handleDelete(id) {
          // 删除
          if (confirm('确定删除吗?')) {
            // console.log(id)
              this.deleteTodo(id)
          }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    底部统计

    完成事件统计

    首先将todos传给myitem

    //App.vue
     
    
    • 1
    • 2
    //MyFooter.vue
     props:['todos']
    
    • 1
    • 2

    使用计算属性computed实现底部统计

         已完成{{doneTotal}}/全部{{ todos.length }}
    
    • 1
    computed: {
            doneTotal() {
                let i = 0
               this.todos.forEach((todo) => {
                if(todo.done)i++
               });
               return i
            }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    底部统计也可以使用ES6的reduce方法完成一种更为高级的写法

         const x= this.todos.reduce((pre,cur) => {
                    console.log('@', pre, cur)
                    return pre + (cur.done?1:0)
                }, 0)
                console.log('###', x)
                return x
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    精简为一句代码

    return this.todos.reduce((pre,cur)=>pre+(cur.done?1:0),0)
    
    • 1

    pre上一个值,cur当前的值,数组的长度就是函数的调用次数.
    打印pre,0,undefined,undefined。统计的初始值是0,所以第一次调用是0,再调用的时候,pre是第一次调回的函数的返回值,第一次调用没有返回值,所以第二次和第三次都是undefined。如果有return 3,那么第二次和第三次pre都是3.所以返回值应该是return pre+1.这样第一次返回值是1,第二次是2,第三次是3。所以最后3就是reduce的返回值。

    底部交互-无任务时显示为空

    全部{{ total}}
    computed: {
            total() {
                return this.todos.length
            },
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    当任务为0时,不显示底部

    
    
    
    checkAllTodo(done) {
          this.todos.forEach((todo) => {
             todo.done=done
          })
         
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Myfooter.vue中props接收传值,然后方法调用

     props: ['todos','checkAllTodo'],
    
     methods: {
            checkAll(e) {
                console.log(e.target.checked)//借助属性拿到Dom没有操作DOM
                this.checkAllTodo(e.target.checked)
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    优化方案

    v-model替换
    在这里插入图片描述

    点击勾选框,[Vue warn]: Write operation failed: computed property “isAll” is readonly.
    将isAll改为计算属性

    isAll(){}改成isAll: {}
    
    • 1

    清空已完成任务

    思路:给清空已完成的按钮设置click事件clearAll
    methods设置方法clearAll,clearAll调用App入口文件的clearAllTodo方法,给myfooterclearAllTodo传给MyFooter组件

        clearAllTodo() {
            this.todos=this.todos.filter((todo) => {
            return !todo.done
          })
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    MyFooter文件使用props接收文件。

    总结

    1. 组件化编程流程:
      (1)拆分静态组件:组件按照功能点拆分,命名不与html元素冲突。
      (2)实现动态组件:考虑好数据的存放位置,数据是一个组件在用(放在组件自身),还是一些组件在用(放在共同的父组件上面)。
      (3)实现交互:从绑定事件开始。
    2. props适用于:
      (1).父组件=>子组件 通信
      (2).子组件==>父组件通信(父组件先给子组件一个函数)
    3. 使用v-model时要切记:v-model绑定的值不能使props传过来的,因为props是不可以修改的
    4. props传过来的若是对象类型的值,修改对象中的属性Vue不会报错,但不推荐这样做
      {}
    ## 清空已完成任务
    > 思路:给清空已完成的按钮设置click事件clearAll
    methods设置方法clearAll,clearAll调用App入口文件的clearAllTodo方法,给myfooterclearAllTodo传给MyFooter组件
    
    • 1
    • 2
    • 3
    clearAllTodo() {
        this.todos=this.todos.filter((todo) => {
        return !todo.done
      })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    MyFooter文件使用props接收文件。

    总结

    1. 组件化编程流程:
      (1)拆分静态组件:组件按照功能点拆分,命名不与html元素冲突。
      (2)实现动态组件:考虑好数据的存放位置,数据是一个组件在用(放在组件自身),还是一些组件在用(放在共同的父组件上面)。
      (3)实现交互:从绑定事件开始。
    2. props适用于:
      (1).父组件=>子组件 通信
      (2).子组件==>父组件通信(父组件先给子组件一个函数)
    3. 使用v-model时要切记:v-model绑定的值不能使props传过来的,因为props是不可以修改的
    4. props传过来的若是对象类型的值,修改对象中的属性Vue不会报错,但不推荐这样做
  • 相关阅读:
    【初阶数据结构】——带头双向循环链表(C描述)
    dubbo核心源码流程分析
    Squid服务
    【Redis】内存回收:内存淘汰策略
    分享这几个好用的文字识别软件,教你快速识别
    C++面向对象程序设计(第2版)第五章(继承与派生)知识点总结
    高绩效团队的打造,助力企业战略目标达成
    简单的咖啡文化静态HTML网页设计作品 DIV布局咖啡馆文化网页模板代码 DW咖啡网站制作成品
    第七章:Sysml之序列图
    【Vue】Vue的v-if、v-if-else、v-else-if、v-show的使用
  • 原文地址:https://blog.csdn.net/weixin_55355282/article/details/132910562