父组件
<template>
<!-- 1-视图层 -->
<div class="todo-container">
<div class="todo-wrap">
<Header ref="head"/>
<!-- 原来的属性绑定模式(:deleteAll),则变换成了事件监听模式(@deleteAll),并且是自定义事件的名称 -->
<!-- updataAll(val)报错,需要写成updataAll($event),才能传递参数 -->
<Footer
:todos="todos"
@updataAll="updataAll"
@deleteAll="deleteAll"/>
</div>
</div>
</template>
<script>
// 2-逻辑层
import Header from "@/components/Header"
import Footer from "@/components/Footer"
export default {
name: "App",
data(){
return {
// 拿到localStorage的todos,把字符串转为对象
// 因为一开始todos是没有值的,为null,所以需要设置为空数组
todos:JSON.parse(localStorage.getItem("todos")) || [],
}
},
components:{
Header,
Footer,
},
methods:{
// 添加数据
addTodo(todo){
this.todos.unshift(todo)
},
// 点击全部更改所有按钮
updataAll(val){
// 如果事件监听的时候不进行实参传递,则可以进行形参的设置,并且该形参将接收到emit传递过来的自定义参数数据
// 如果监听函数需要进行参数传递,那么则可以利用$event进行自定义数据的传递操作
this.todos.forEach(item=>(item.isOver=val))
},
// 清除已完成任务
deleteAll(){
// 设置一个新数组,将原来isOver为true的元素过滤掉
this.todos=this.todos.filter(item=>item.isOver===false)
}
},
watch:{
todos:{
handler(newVal, oldVal){
// 监听todos,把他转为字符串,存储到localStorage
localStorage.setItem("todos",JSON.stringify(newVal));
},
immediate:true,
deep:true
}
},
mounted(){
this.$refs.head.$on("addTodo",this.addTodo)
},
beforeDestroy(){
// 如果撤离销毁了组件,取消监听
this.$refs.head.$off("addTodo")
}
};
</script>
子组件
<template>
<div class="todo-footer">
<label>
<!-- v-model不一定要绑定data声明的数据 -->
<!-- 这里v-model绑定的是computed属性计算的值 -->
<input type="checkbox" v-model="checkAll"/>
</label>
<span> <span>已完成{{overNum}}</span> / 全部{{allNum}} </span>
<button class="btn btn-danger" @click="deleteA">清除已完成任务</button>
</div>
</template>
<script>
export default {
name:"Footer",
props:["todos","updataAll","deleteAll"],
methods:{
deleteA(){
// this.deleteAll()
// 从回调模式改成了子与父之间的自定义事件的通讯
// 自定义事件可以不传递参数
this.$emit("deleteAll")
}
},
computed:{
allNum(){
return this.todos.length;
},
overNum(){
// 第一种
// return this.todos.filter(item=>item.isOver).length
// 第二种
return this.todos.reduce((prev,item)=>{
if(item.isOver) prev+=1;
return prev
},0)
},
checkAll:{
get(){
// 满足 this.allNum===this.overNum 的情况下 并且 this.allNum>0
// 需要满足两个条件 才为true
return this.allNum===this.overNum && this.allNum>0
},
set(val){
// 一开始为false,点击按钮以后设置为true,依次更改
console.log(val)
// this.updataAll(val)
// emit也可以进行参数传递
this.$emit('updataAll',val)
}
}
}
};
</script>