跳到主要内容

认识

2024年03月18日
柏拉文
越努力,越幸运

一、认识


一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个 property

二、语法


var vm = new Vue({
data: {
a: 1,
b: 2,
c: 3,
d: 4,
e: {
f: {
g: 5
}
}
},
watch: {
a: function (val, oldVal) {
console.log('new: %s, old: %s', val, oldVal)
},
// 方法名
b: 'someMethod',
// 该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深
c: {
handler: function (val, oldVal) { /* ... */ },
deep: true
},
// 该回调将会在侦听开始之后被立即调用
d: {
handler: 'someMethod',
immediate: true
},
// 你可以传入回调数组,它们会被逐一调用
e: [
'handle1',
function handle2 (val, oldVal) { /* ... */ },
{
handler: function handle3 (val, oldVal) { /* ... */ },
/* ... */
}
],
// watch vm.e.f's value: {g: 5}
'e.f': function (val, oldVal) { /* ... */ }
}
})
vm.a = 2 // => new: 2, old: 1

三、对比


3.1 computed vs watch

watch 为每一项实例化一个 Watcher 实例, 创建如下 const watcher = new Watcher(vm, expOrFn, cb, { user:true, deep: options.deep }), 用于监听已有响应式依赖的变化, 如有变化, 触发回调。

computed 为每一项实例化一个 Watcher 实例, 创建如下 watchers[key] = new Watcher( vm, getter || noop, noop, { lazy: true } ), 并将 computed 的属性 key 代理到 Vue 实例上。 因此, Computed Watcher 是基于其他响应式数据经过一些处理后生成的一个新的响应式状态, 同 data 一致。传入 lazy 配置项, 表示不会立即执行回调函数并计算结果, 只有访问 computed 属性时, 触发 get 函数执行, 检测 watcher.dirty 标记是否为 true, 为 true 表示在本次渲染周期内没有被执行过, 随后执行回调函数计算结果, 计算时, 所依赖的响应式数据同样会收集当前 Computed Watcher。如果 watcher.dirtyfalse, 直接返回计算结果, 具有缓存的作用。

3.2 computed vs methods

如果在一次渲染中,有多个地方使用了同一个 methodscomputed 属性,methods 会被执行多次,而 computed 的回调函数则只会被执行一次。

通过阅读源码我们知道,在一次渲染中,多次访问 computedProperty,只会在第一次执行 computed 属性的回调函数,后续的其它访问,则直接使用第一次的执行结果(watcher.value),而这一切的实现原理则是通过对 watcher.dirty 属性的控制实现的。而 methods,每一次的访问则是简单的方法调用(this.xxMethods)。