1、安装 npm i --save pubsub-js
2、引入 import PubSub from 'pubsub-js'
1 <template> 2 <li 3 @mouseenter="dealShow(true)" 4 @mouseleave="dealShow(false)" 5 :style="{backgroundColor: bgColor}" 6 > 7 <label> 8 <input type="checkbox" v-model="todo.finished"/> 9 <span>{{todo.title}}</span> 10 </label> 11 <button v-show="isShowDelButton" class="btn btn-warning" @click="delItem">删除</button> 12 </li> 13 </template> 14 15 <script> 16 import PubSub from 'pubsub-js' 17 export default { 18 name: "Item", 19 props: { 20 todo: Object, 21 index: Number, // 当前任务在总任务数组中的下标位置 22 delTodo: Function 23 }, 24 data(){ 25 return{ 26 isShowDelButton: false, // false 隐藏 true 显示 27 bgColor: '#fff' 28 } 29 }, 30 methods: { 31 dealShow(isShow){ 32 // 控制按钮的显示和隐藏 33 this.isShowDelButton = isShow; 34 // 控制背景颜色 35 this.bgColor = isShow ? '#ddd' : '#fff'; 36 }, 37 38 delItem(){ 39 if(window.confirm(`您确定删除 ${this.todo.title} 吗?`)){ 40 // this.delTodo(this.index); 41 // 发布消息 42 PubSub.publish('delTodo', this.index) 43 } 44 } 45 } 46 } 47 </script> 48 49 <style scoped> 50 li { 51 list-style: none; 52 height: 36px; 53 line-height: 36px; 54 padding: 0 5px; 55 border-bottom: 1px solid #ddd; 56 } 57 58 li label { 59 float: left; 60 cursor: pointer; 61 } 62 63 li label li input { 64 vertical-align: middle; 65 margin-right: 6px; 66 position: relative; 67 top: -1px; 68 } 69 70 li button { 71 padding: 4px 10px; 72 float: right; 73 margin-top: 3px; 74 } 75 76 li:before { 77 content: initial; 78 } 79 80 li:last-child { 81 border-bottom: none; 82 } 83 </style>
1 <template> 2 <div class="todo-container"> 3 <div class="todo-wrap"> 4 <Header ref="header"/> 5 <List :todos="todos" :delTodo="delTodo"/> 6 <Footer> 7 <input slot="isCheck" type="checkbox" v-model="isCheck"/> 8 <span slot="finish">已完成{{finishedCount}}件 / 总计{{todos.length}}件</span> 9 <button slot="delete" class="btn btn-warning" @click="delFinishedTodos">清除已完成任务</button> 10 </Footer> 11 </div> 12 </div> 13 </template> 14 15 <script> 16 // 引入组件 17 import Header from './components/Header' 18 import List from './components/List' 19 import Footer from './components/Footer' 20 21 // 引入工具类 22 import localStorageUtil from './utils/localStorageUtil' 23 import PubSub from 'pubsub-js' 24 25 export default { 26 name: 'app', 27 data() { 28 return { 29 todos: localStorageUtil.readTodos() 30 } 31 }, 32 computed: { 33 finishedCount() { 34 return this.todos.reduce((total, todo) => total + (todo.finished ? 1 : 0), 0); 35 }, 36 isCheck: { 37 get() { 38 return this.finishedCount === this.todos.length && this.todos.length > 0 39 }, 40 set(value) { 41 this.selectedAllTodo(value); 42 } 43 } 44 }, 45 components: { 46 Header, 47 List, 48 Footer 49 }, 50 mounted(){ 51 // 绑定自定义事件(addTodo)监听 52 this.$refs.header.$on('addTodo', this.addTodo); 53 // 订阅消息(delTodo) 54 PubSub.subscribe('delTodo', (msg, token)=>{ 55 // console.log(msg, token); msg=delTodo token 参数 56 this.delTodo(token); 57 }); 58 }, 59 methods:{ 60 // 插入一条数据 61 addTodo(todo){ 62 this.todos.unshift(todo); 63 }, 64 // 根据索引删除一条记录 65 delTodo(index){ 66 this.todos.splice(index, 1); 67 }, 68 // 是否选中所有的任务 69 selectedAllTodo(isCheck){ 70 this.todos.forEach(todo => { 71 todo.finished = isCheck 72 }) 73 }, 74 delFinishedTodos(){ 75 this.todos = this.todos.filter(todo=> !todo.finished) 76 } 77 }, 78 watch: { 79 // 深度监视 80 todos: { 81 handler: localStorageUtil.saveTodos, 82 deep: true, // 深度监视 83 // immediate: true 84 } 85 } 86 } 87 </script> 88 89 <style> 90 .todo-container { 91 width: 600px; 92 margin: 0 auto; 93 } 94 95 .todo-container .todo-wrap { 96 padding: 10px; 97 border: 1px solid #ddd; 98 border-radius: 5px; 99 } 100 </style>
子组件向父组件传值 props:向父组件的函数传递参数;自定义事件;发布订阅