(1) 组件拆分:(1)静态模板 (2)动态模板 (3)数据交互
(2) 组件之间的通信,数值的确定,计算属性的应用,数组的方法
(3) 计算使用,数值的总和,双向数据绑定使用,你的数值变化时候,其他数值也发生变化
(4)本地存储使用
App.vue
<template> <div class="todo-container"> <div class="todo-wrap"> <todo-header :todos="todos" :addItem="addItem"/> <todo-list :todos="todos" :DeleteItem="DeleteItem"/> <todo-footer :todos="todos" :deleteCompleteTodos="deleteCompleteTodos" :selectAll="selectAll"/> </div> </div> </template> <script> import TodoFooter from "./components/TodoFooter"; import TodoHeader from "./components/TodoHeader"; import TodoList from "./components/TodoList"; export default { //默认暴露一个模块 components:{ TodoFooter, TodoHeader, TodoList }, methods:{ addItem(item){ this.todos.splice(0,0,item); }, DeleteItem(index){ this.todos.splice(index,1); }, deleteCompleteTodos(){ //删除todolist里面为true的,过滤 this.todos = this.todos.filter((todo)=> todo.complete===false ) }, selectAll(flag){ //所有的都为true表示选中,都为false也勾选,点击的时候勾选 this.todos.forEach((todo) => todo.complete=flag) } }, watch:{ todos: { handler: function (val, oldVal) { //存入到本地 window.localStorage.setItem("todos_key",JSON.stringify(val)) }, deep: true } }, data(){ return{ //页面加载的时候取出 todos:JSON.parse(window.localStorage.getItem("todos_key") ||"[]") } } } </script> <style> .todo-container { 600px; margin: 0 auto; } .todo-container .todo-wrap { padding: 10px; border: 1px solid #ddd; border-radius: 5px; } </style>
TodoHeader.vue
<template> <div class="todo-header"> <input type="text" @keyup.enter="add" placeholder="请输入你的任务名称,按回车键确认" v-model="title" /> </div> </template> <script> export default { //默认暴露一个模块 props:{ todos:Array, addItem:Function }, data(){ return { title:"" } }, methods:{ add(){ //信息添加进去 const {title,addItem} = this; const item = { title, complete:false } if(title.trim()){ addItem(item) } } } } </script> <style> .todo-header input { 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>
TodoList.vue
<template> <ul class="todo-main"> <TodoItem v-for="(todo,index) in todos" :key="index" :todo="todo" :DeleteItem="DeleteItem" :index="index"/> </ul> </template> <script> import TodoItem from "./TodoItem" export default { //默认暴露一个模块 props:{ todos:Array, DeleteItem:Function }, components:{ TodoItem } } </script> <style> .todo-main { margin-left: 0px; 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>
TodoItem.vue
<template> <li @mouseenter="EnterItem(true)" @mouseleave="EnterItem(false)" :style="{background:bgColor }"> <label> <input type="checkbox" v-model="todo.complete"/> <span>{{todo.title}}</span> </label> <button class="btn btn-danger" v-show="isShow" @click="deleteItem">删除</button> </li> </template> <script> export default { //默认暴露一个模块 methods:{ EnterItem(isEnter){ if(isEnter){ //进入显示 this.isShow =true; this.bgColor = "#aaa" }else{ this.isShow =false; this.bgColor = "white"; } }, deleteItem(){ if(confirm("确认是否删除")){ const {index,DeleteItem} = this; DeleteItem(index); } } }, data(){ return{ isShow:false, bgColor:"white" } }, props:{ todo:Object, DeleteItem:Function, index:Number }, } </script> <style> 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; } </style>
TodoFooter.vue
<template> <div class="todo-footer"> <label> <input type="checkbox" v-model="checkAll"/> </label> <span> <span>已完成{{completeSize}}</span> / 全部{{todos.length}} </span> <button class="btn btn-danger" v-show="completeSize" @click="AllTask">清除已完成任务</button> </div> </template> <script> export default { //默认暴露一个模块 props: { // 需要使用,数组数据,函数,清除, todos: Array, deleteCompleteTodos: Function, selectAll: Function }, methods: { AllTask() { this.deleteCompleteTodos(); } }, computed: { completeSize () { return this.todos.reduce((preTotal, todo) => preTotal + (todo.complete?1:0) ,0) }, checkAll: { get () { // 决定是否勾选 return this.completeSize===this.todos.length && this.completeSize>0 }, set (value) {// 点击了全选checkbox value是当前checkbox的选中状态(true/false) this.selectAll(value) } }, } } </script> <style> .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>