> 技术文档 > Vue TodoList案例

Vue TodoList案例


一、总结TodoList案例

  1. 组件化编码流程:

    (1).拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突。

    (2).实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用:

            (1.一个组件在用:放在组件自身即可。

            (2. 一些组件在用:放在他们共同的父组件上(状态提升)。

    (3).实现交互:从绑定事件开始。

  2. props适用于:

    (1).父组件 ==> 子组件 通信

    (2).子组件 ==> 父组件 通信(要求父先给子一个函数)

  3. 使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!

  4. props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。

二、Components

        1.App.vue:

 
import { nanoid } from \'nanoid\' export default { name:\'Add\', data() { return { todo:\'\', } }, props:[\'addTodo\'], methods:{ loseFocus(){ this.$refs.addInput.blur() }, add(){ const todoObj = {id:nanoid(),text:this.todo,is_check:false} this.addTodo(todoObj) this.todo=\'\' }, } } .add-todo{ padding-bottom: 10px; } .add-input { width: 350px; height: 40px; padding: 0 10px; font-size: 16px; border: 1px solid #000; border-radius: 4px; }

        2.allTodo.vue:

 
<!-- --> 已完成{{ finish }}/全部{{ todoList.length }} <!-- -->
export default { name:\'allTodo\', props:[\'todoList\',\'allTodoDelete\',\'toggleAll\'], computed:{ allCompeled:{ get(){ return this.todoList.length > 0 && this.todoList.every(item => item.is_check) }, set(value){ this.toggleAll(value) } }, finish(){ // return this.todoList.filter(item => item.is_check).length return this.todoList.reduce((pre,current) => pre+(current.is_check?1:0),0) }, show(){ return this.finish>0 // return this.finish>0 ? \'block\' : \'none\' } }, methods: { // toggleTodoAll(e){ // console.log(e.target.checked) // this.toggleAll(e.target.checked) // }, todoDelete(){ this.allTodoDelete() } }, } .all-todo{ display: flex; height: 30px; padding-top: 10px; } .todo-item-delete{ // display: none; height: 30px; background-color: red; color: #fff; border-radius: 4px; cursor: pointer; margin-left: auto; border: none; &:hover { background-color: #f5222d; } }

        3.todoList.vue:

 
import todoItem from \'./todoItem.vue\'; export default { name:\'todoList\', props:[\'todoList\',\'todoDelete\',\'itemCheckChange\'], components:{ todoItem } } .todo-list{ width: 350px; display: flex; flex-direction: column; border: 1px solid #ccc; border-radius: 4px; overflow: hidden; /* 防止边框圆角被内容覆盖 */ padding: 0 10px; }

        4.todoItem.vue:

 
<!-- --> {{ item.text }}
export default { name:\'todoItem\', props:[\'item\',\'todoDelete\',\'itemCheckChange\'], methods: { todosDelete(id){ this.todoDelete(id) }, checkChange(id){ this.itemCheckChange(id) } }, } .todo-item{ height: 30px; display: flex; align-items: center; padding: 10px 15px; border-bottom: 1px solid #eee; &:hover { background-color: #e8e8e8; .todo-item-delete { display: block; } } } .todo-item-delete{ display: none; height: 30px; background-color: red; color: #fff; border-radius: 4px; cursor: pointer; margin-left: auto; border: none; &:hover { background-color: #f5222d; } } .todo-item:last-child { border-bottom: none; }

        5.App.vue:

 
import Add from \'./Components/Add.vue\' import todoList from \'./Components/todoList.vue\'; import {nanoid} from \'nanoid\' import allTodo from \'./Components/allTodo.vue\'; export default { name:\'App\', data() { return { todoList:[ { id:nanoid(), text:\'test\', is_check:false } ] } }, components:{Add,todoList,allTodo}, methods:{ addTodo(x){ if(x.text.trim()){ this.todoList.unshift(x) } }, allTodoDelete(){ this.todoList = this.todoList.filter(item => !item.is_check) }, todoDelete(id){ this.todoList = this.todoList.filter(item=>item.id!=id) }, itemCheckChange(id){ this.todoList.forEach(item=>{ if(item.id === id) item.is_check =!item.is_check }) }, toggleAll(value){ this.todoList.forEach(item => { item.is_check=value }) } }, } .centent{ width: 400px; margin: auto; border: 1px solid #000; min-height: 50px; padding: 20px; }