computed 与 watch 之间的那点事儿
computed
- 计算属性的值
在依赖数据发生改变时 / 或者没有依赖数据时
会自动缓存到应用中,下次获取时,不重新计算 - 计算得到的数据
- computed 是一个对象,里面存放是属性,类似 data 而不是methods
- 里面的属性可以像 data 里面存放的数据一样去使用
- 这些属性的值是通过运算得到的
- 它的结构类似(defineProperty), getter , setter
- 计算属性的值同时还会根据它所依赖的数据变化 而自动变化
<div id="app">
<button @click="showData=!showData">click</button>
<p v-if="showData">实时数据:{{getNow()}}</p>
<p v-if="showData">computed 的数据:{{now}}</p>
</div>
<script>
let app = new Vue({
el:"#app",
data:{
showData:true
},
methods:{
getNow(){
return Date.now()
}
},
computed:{
// 完整的写法如下:
// now:{
// get(){
// return Date.now();
// }
// },
/*
* 如果某个计算属性只需要处理 get方法,那么可以简写
* 只是简写,并不是直接放置方法
*/
now(){
return Date.now();
}
}
});
</script>
- 多次点击按钮
查看 computed 的监听性质
实时数据一直改变,computed 的数据并没有发生改变
watch
计算属性 / 计算数据 / 派生数据
- watch 异步的派生数据
可以用来直接处理异步
可以达到主动监听的效果,只要监听的属性或者数据发生变化,立即触发事件
监听不同类型数据
- 简单数据类型监听
watch:{
// users 需要监听的数据(属性)
// (){} 数据发生改变时 调用的回调函数
users(){
console.log(111)
if (this.users.every(user => user.checked == true)) {
this.checkAll = true;
}else{
this.checkAll = false;
}
}
}
- 数组类型数据监听
watch:{
showUsers:{
// watch 默认监听数据一层
// 深度监听 handler 方法和 deep 属性结合
handler(arr){
// console.log(arr);
let all = arr.every(user => user.checked == true);
console.log(all);
if (all == true ) {
this.checkAll = true;
}else{
this.checkAll = false;
}
}
},
}
- 多层对象数据监听
watch: {
'a.b.c': function() {
//...
}
}
模拟实例
搜索框失去焦点立即触发事件
修改显示元素的 display 属性
<style>
.active{
color: coral;
font-weight: bold;
}
</style>
<div id="app">
<!--
通过 v-model 实现监听事件
-->
输入性别: <input type="text" v-model.lazy="keyWord">
<ul>
<li v-for="user in showUsers">
<input type="checkbox" v-model="user.checked">
{{user.name}}-{{user.sex}}
</li>
</ul>
</div>
<script>
let users = [
{id:1,name:"秦",age:"23",sex:"男",checked:false},
{id:2,name:"兟",age:"22",sex:"男",checked:false},
{id:3,name:"李",age:"24",sex:"女",checked:false},
{id:4,name:"武",age:"23",sex:"女",checked:false},
]
let app = new Vue({
el:"#app",
data:{
keyWord:"",
users,
showUsers:[]
},
watch:{
// v-model 监听的 keyWord 事件
keyWord(){
// includes(指定的内容); 是否包含指定的值
this.showUsers = this.users.filter(user => user.sex.includes(this.keyWord))
}
}
});
</script>
computed 和 watch 的区别
对于数据的处理:
- computed : 依赖数据变化才去计算
- watch: 主动处理数据变化
是否处理异步(能否主动监听)
- computed: 没法处理异步的数据
- watch:可以直接处理异步
使用场景
- computed: 适合的场景 多个数据影响一个数据
数据不独立的场景 - watch:适合的场景 一个数据影响多个数据
适合处理数据相互独立的场景
watch实现
会有一定的弊端,watch 实现全选的写法上会有自身的问题
<div id="app">
<button :class="{active:sex===''}" @click = "sex=''">全部</button>
<button :class="{active:sex==='男'}" @click = "sex='男'">男</button>
<button :class="{active:sex==='女'}" @click = "sex='女'">女</button>
<hr>
<ul>
<li v-for="user in showUsers">
<input type="checkbox" v-model="user.checked">
{{user.name}}-{{user.sex}}-{{user.age}}
</li>
</ul>
<input type="checkbox" v-model="checkAll">全选
</div>
<script>
let users = [
{id:1,name:"秦",age:"23",sex:"男",checked:false},
{id:2,name:"兟",age:"22",sex:"男",checked:false},
{id:3,name:"李",age:"24",sex:"女",checked:false},
{id:4,name:"武",age:"23",sex:"女",checked:false},
{id:5,name:"谭",age:"22",sex:"女",checked:false}
]
let app = new Vue({
el:"#app",
data:{
sex:"",
users,
checkAll:false,
showUsers:users
},
/* 监听某一个对象 */
watch:{
sex(){
this.showUsers = this.users;
if (this.sex != "") {
this.showUsers = this.users.filter(user => user.sex == this.sex);
}
},
checkAll(){
if (!this.showUsers.some(e => e.checked)) {
this.users.forEach(el => {
el.checked = this.checkAll;
});
}
},
// 数组的类型监听
showUsers:{
// watch 默认监听数据一层
// 深度监听 handler 方法和 deep 属性结合
handler(arr){
// console.log(arr);
let all = arr.every(user => user.checked == true);
console.log(all);
if (all == true ) {
this.checkAll = true;
}else{
this.checkAll = false;
}
},
immediate:true, // 主动执行一次
deep:true // 默认 false 只监听一层
}
}
});
</script>