问题引入:data 变化时除了更新视图,还能做什么?
1、computed - 计算属性
即被计算出来的属性,它是一个函数,直接引用该属性即显示函数的返回值。
两种写法:
- 函数
computed:{
xxx(){...}
}
- getter/setter
computed:{
xxx:{
get(){...}
set(value){...}
}
}
用途:展示对 data 中的数据进行处理后的结果
{
data:{
a: 0
},
computed:{
processA(){
return ... //a处理后的值
}
},
template:`
<div>{{processN}}</div>
`
}
当 data 中的数据变化时,触发视图更新,其中依赖于 data 的计算属性会重新计算(即执行了相应的函数)
计算属性有缓存处理,如果其依赖的 data 没有变化,则不会重新计算
2、watch - 侦听
用途:当 data 变化时,执行一个函数
{
data:{
n:0,
obj:{
a: 0
}
},
watch:{
n(newValue, oldValue){...}, //侦听n
'obj.a'(){...} //侦听obj.a
}
}
执行时会传入新值(newValue
)、旧值(oldValue
)
【注】:
watch 是异步的,它不会在n
变化后立即执行,而是在当前同步任务结束后才会执行 watch
Vue 提供了 this.$nextTick
方法来创建新异步任务:
this.$nextTick(fn, 0)
上述 watch 的写法在第一此渲染时并不会执行,写为如下的对象形式,则第一次渲染也会执行:
{
watch:{
'obj.a': {
handler(){...}, //待执行的函数
immediate: true
}
}
}
何为 data 变化?
考虑如下 data:
data:{
n:0,
obj:{
a: 0
}
}
侦听其中的n
obj
obj.a
- 改变
n = 1
---> 执行n的侦听 - 改变
obj.a = 1
---> 仅执行obj.a的侦听 - 改变
obj = {a: 0}
---> 仅执行obj的侦听,obj.a的侦听不执行
【结论】:简单类型看值的变化,复杂类型看地址的变化
如何实现改变 obj.a,obj 的侦听亦执行?---------> 用deep: true
watch:{
obj:{
handler(){...},
deep:true
}
}
watch 完整用法
watch:{
a: function(){},
b: 'methodName', //methods 中的方法
c: {
handler(){},
deep: true,
immediate: true
},
d: [f1,f2,f3], //依次执行f1 f2 f3 ...
'obj.e': function(){}
}
此外,还可以用 Vue 实例的 '$watch'
方法:
vm.$watch('f', fn, {deep:true, immediate:true})
3、总结:computed 和 watch 区别
两者均会在 data 变化时执行某个函数,但也有区别
- computed
目的是得到一个依赖于 data 的值,虽然写为方法的形式,但可以当作 Vue 实例的属性一样,不用加括号直接获取其返回值。
并且,computed 还做了缓存处理,即 data 变化时,若被 computed 依赖的部分没有变,则不会再次进行计算。
- watch
watch 则是用来监听 data 中的属性,当其变化时,执行回调。其目的并非一定要得到某个依赖于 data 的值,因此它的使用情景可以比 computed 更广泛。