vue part 7

avatar
作者
筋斗云
阅读量:0

To Do List案例

MyFooter.vue
<template>   <!--隐式类型转换-->   <div class="todo-footer" v-show="total">     <label>       <!--这里也可用v-model来替代,此时不需要计算属性了--> <!--      <input type="checkbox" :checked="isAll" @change="checkAll"/>-->       <input type="checkbox" v-model="isAll"/>     </label>     <span>        <span>已完成{{ doneTotal }}</span> / 全部{{total}}     </span>     <button class="btn btn-danger" @click="clearAll">清除已完成任务</button>   </div> </template> <script> export default {   name: "MyFooter",   props: ['todos', 'checkAllTodo', 'clearAllDoneTodo'],   computed:{     total(){       return this.todos.length;     },     doneTotal(){       return this.todos.reduce((todoTotal, todo) => {         //隐士类型转换         return todoTotal + todo.done;       }, 0);       // return this.todos.filter(todo => todo.done).length;     },     isAll:{       get(){         return this.total === this.doneTotal && this.doneTotal > 0; //计算属性可以通过其他的计算属性接着进行计算得到结果       },       set(value){         //value注意要么为true,要么为false,因为你是把它应用在了checkbox上         this.checkAllTodo(value);       }     }   },   methods:{     // checkAll(e){     //   // console.log(e.target.checked); //判断这个checkbox到底是不是全选 true全选 false全不选     //   this.checkAllTodo(e.target.checked);     // }     clearAll(){        this.clearAllDoneTodo();     }   } } </script>  <style scoped> /*footer*/ .todo-footer {   height: 40px;   line-height: 40px;   padding-left: 6px;   margin-top: 5px; }  .todo-footer label {   display: inline-block;   margin-right: 20px;   cursor: pointer; }  .todo-footer label input {   position: relative;   top: -1px;   vertical-align: middle;   margin-right: 5px; }  .todo-footer button {   float: right;   margin-top: 5px; } </style> 
MyHeader.vue
<template>   <div class="todo-header">     <input type="text" placeholder="请输入你的任务名称,按回车键确认" v-model="title" @keyup.enter="add"/>   </div> </template>  <script> import { nanoid } from 'nanoid'; export default {   //注意不管是你写的data也还还是methods也好,甚至是computed计算属性也好都会出现在组件事例对象vc身上   //属性值不能重名   name: "MyHeader",   data(){     return {       title: ''     }   },   methods:{     add(){       //将用户的输入包装成一个todo对象       console.log(this.title)       if(!this.title.trim()) {//这个判断的意思就是,如果输入框为空,就跳出这个函数,为什么要取反?因为字符串转为布尔值就是false,所以得取反为true,跳出函数。 //意思就是如果传过来的todo的title也就是输入的值为空的话,就return跳出函数了         alert('代办事项不能为空')         return; //输入的代办事项为空则不走下面流程       }       const todoObj = {         id: nanoid(),//简单的库,比uuid快和轻便很多         title: this.title,         done:false       }//这是兄弟组件,不是父子组件,传数据失败,header和list不互通       //props一般是单向通信,即父传子,官方不建议子传父,会导致数据流向难以理解。       //       // console.log(todoObj);       this.addTodo(todoObj)       this.title = '';     }   },   props:['addTodo'], } </script>  <style scoped> /*header*/ .todo-header input {   width: 560px;   height: 28px;   font-size: 14px;   border: 1px solid #ccc;   border-radius: 4px;   padding: 4px 7px; }  .todo-header input:focus {   outline: none;   border-color: rgba(82, 168, 236, 0.8);   box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); } </style> 
Item.vue
<template>   <li>     <label> <!--      这里勾选和取消勾选可以使用change和click作为事件处理-->       <input type="checkbox" :checked="todo.done" @change="handleCheck(todo.id)"/>       <!--v-model数据的双向绑定,checkbox使用v-model来双向绑定其是否被勾选,也可以实现效果但不推荐(因为其实修改了props中的数据)-->       <!--这里修改了从List修改过来的props,这里的不允许改是浅层次,就是如果props是一个对象则这个修改这个对象的某一个属性vue是放行的-->       <!-- <input type="checkbox" v-model="todo.done"/>-->       <!-- 这里时props传入的数据,不宜使用v-model,因为不允许在子组件中修改父组件的数据 -->         <span>{{  todo.title }}</span>     <!--@change 原型 是js里面的onchange 当input表单value发生改变触发事件-->     </label>     <button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>   </li> </template>  <script> export default {   name: "Item",   //声明接收todo   props: ['todo', 'checkTodo', 'deleteTodo'],   methods:{     handleCheck(id){       this.checkTodo(id);     },     handleDelete(id){       if(confirm(`确定删除编号为${id}的todo吗`)){         // console.log(id);         this.deleteTodo(id);       }     }   } } </script>  <style scoped> /*item*/ li {   list-style: none;   height: 36px;   line-height: 36px;   padding: 0 5px;   border-bottom: 1px solid #ddd; }  li label {   float: left;   cursor: pointer; }  li label li input {   vertical-align: middle;   margin-right: 6px;   position: relative;   top: -1px; }  li button {   float: right;   display: none;   margin-top: 3px; }  li:before {   content: initial; }  li:last-child {   border-bottom: none; }  li:hover{   background: #ddd; }  li:hover button{   display: block; } </style> 
List.vue
<template>   <ul class="todo-main">     <Item         v-for="todoObj in todos"         :key="todoObj.id"         :todo="todoObj"         :checkTodo="checkTodo"         :deleteTodo="deleteTodo"     />   </ul> </template>  <script> import Item from "@/components/Item";  export default {   name: "List",   components: {     Item,   },   props:['todos', 'checkTodo', 'deleteTodo'] } </script>  <style scoped> /*main*/ .todo-main {   margin-left: 0;   border: 1px solid #ddd;   border-radius: 2px;   padding: 0px; }  .todo-empty {   height: 40px;   line-height: 40px;   border: 1px solid #ddd;   border-radius: 2px;   padding-left: 5px;   margin-top: 10px; } </style> 
App.vue
<template>   <div id="root">     <div class="todo-container">       <div class="todo-wrap">         <MyHeader :addTodo="addTodo"/>         <List             :todos="todos"             :checkTodo="checkTodo"             :deleteTodo="deleteTodo"         />         <MyFooter             :todos="todos"             :checkAllTodo="checkAllTodo"             :clearAllDoneTodo="clearAllDoneTodo"         />       </div>     </div>   </div> </template>  <script> import MyHeader from "@/components/MyHeader"; import List from "@/components/List"; import MyFooter from '@/components/MyFooter'; export default {   name: "App",   components:{     List,     MyFooter,     MyHeader   },   data() {     return {       todos: [         {id: '001', title: '吃饭', done: false},         {id: '002', title: "睡觉", done: true},         {id: '003', title: '打代码', done: false}       ]     }   },   methods:{     //添加的todo     addTodo(todo){       console.log('我是app组件,我收到了数据');       this.todos.unshift(todo);     },     checkTodo(id){       const todo = this.todos.find(todo => todo.id === id);       todo.done = !todo.done;     },     deleteTodo(id){       this.todos = this.todos.filter(todo => todo.id !== id);     },     checkAllTodo(done){       this.todos.forEach(todo => todo.done = done);     },     clearAllDoneTodo(){       this.todos = this.todos.filter(todo => !todo.done)     }   } } </script>  <style> /*base*/ body {   background: #fff; }  .btn {   display: inline-block;   padding: 4px 12px;   margin-bottom: 0;   font-size: 14px;   line-height: 20px;   text-align: center;   vertical-align: middle;   cursor: pointer;   box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);   border-radius: 4px; }  .btn-danger {   color: #fff;   background-color: #da4f49;   border: 1px solid #bd362f; }  .btn-danger:hover {   color: #fff;   background-color: #bd362f; }  .btn:focus {   outline: none; }  .todo-container {   width: 600px;   margin: 0 auto; } .todo-container .todo-wrap {   padding: 10px;   border: 1px solid #ddd;   border-radius: 5px; } /*别人的项目可不这么这么写,CSS写到后面,发现前面的可能要加点什么直接后面补了,真是离了大谱*/ </style>   

全都勾选了有可能是MyList里面的done后面写成了字符串,,把单引号或者双引号去掉就行了

因为你们todoList里面是“true”而不是true,done 要写布尔值,不要写字符串

父组件定义函数,子组件调用函数传递参数。子组件定义属性参数列表,父组件调用子标签属性传参。这里的this还是header,只不过header和app里的received方法引用地址相同,你在header里面调用了,也相当于在app中调用了

这里this都是 实例对象vc  函数是地址值 不是传进来个全新的对象,在js中,函数也是对象,传函数本身实际上是引用传递,意思他们两用的是同一块内存空间,一方修改,另一方也会改变

header里并没有修改任何值,只是传了个参数回app,app那个this才真正修改了vc上的数据

072_尚硅谷Vue技术_TodoList案例_添加_哔哩哔哩_bilibili 这5分钟很好

关于addtodo,这里是按下回车后调用的add方法与APP传过来的add方法重名了

 勾选

是非常重要,Vue将页面拆分成各种组件,组件间就得通信拿数据,如果不用Vue,就一个页面,数据都在一起那还用啥通信了

@change="todoObj.done=!todoObj.done" 就可以了

v-model底层就是监听checked 绑定change 

    广告一刻

    为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!