vue的wacth实现原理
Vue 的 watch 实现原理
Vue 的 watch 功能通过依赖收集和响应式系统实现,核心是利用 Watcher 类监听数据变化并触发回调。
依赖收集与响应式系统
Vue 的响应式系统基于 Object.defineProperty(Vue 2)或 Proxy(Vue 3)实现数据劫持。当数据被访问时,依赖(即 Watcher 实例)会被收集到当前属性的依赖列表中。数据变化时,依赖列表中的 Watcher 会被通知并执行更新。
Watcher 类的作用
watch 选项或 $watch 方法会创建一个 Watcher 实例。Watcher 负责:

- 解析监听的表达式(如
'a.b.c'),触发对应属性的getter,从而将自身添加到依赖列表中。 - 当数据变化时,触发
setter,通知Watcher执行回调函数。
回调触发机制
Watcher 在数据变化时会通过调度队列(如 queueWatcher)异步执行回调。Vue 通过 nextTick 确保回调在 DOM 更新后执行,避免重复计算和渲染。
深度监听实现
当 deep: true 时,Watcher 会递归遍历监听对象的所有属性,触发它们的 getter,从而收集所有嵌套属性的依赖。任何嵌套变化都会触发回调。

立即执行与旧值获取
immediate: true 时,Watcher 会在创建后立即执行一次回调。回调的参数 newVal 和 oldVal 通过 Watcher 内部缓存的上一次值实现对比。
源码关键逻辑(Vue 2 示例)
// 简化版 Watcher 实现
class Watcher {
constructor(vm, expOrFn, cb, options) {
this.vm = vm;
this.cb = cb;
this.deep = !!options.deep;
this.value = this.get(); // 触发依赖收集
}
get() {
pushTarget(this); // 将当前 Watcher 设为全局依赖
const value = parsePath(this.expOrFn)(this.vm); // 访问数据,触发 getter
if (this.deep) traverse(value); // 深度遍历
popTarget(); // 恢复之前的依赖
return value;
}
update() {
const oldVal = this.value;
this.value = this.get(); // 重新获取新值
this.cb.call(this.vm, this.value, oldVal); // 触发回调
}
}
与 computed 的区别
watch 是主动监听数据变化并执行副作用,而 computed 是惰性求值,只有依赖变化且被访问时才重新计算。computed 会缓存结果,避免重复计算。
总结
Vue 的 watch 通过 Watcher 类、依赖收集和响应式系统实现数据监听。其核心是属性访问时的依赖绑定和变化时的回调调度,支持深度监听、异步更新和旧值比对等功能。






