vue的wacth实现原理
Vue 的 watch 实现原理
Vue 的 watch 功能用于监听数据变化并执行回调函数。其核心实现依赖于 Vue 的响应式系统和依赖收集机制。
响应式系统基础
Vue 通过 Object.defineProperty(Vue 2)或 Proxy(Vue 3)实现数据劫持。当数据被访问时,会触发 getter 进行依赖收集;当数据被修改时,会触发 setter 通知依赖更新。
Watcher 类的角色
watch 的核心是 Watcher 类,它是一个观察者,负责订阅数据变化并执行回调。每个 watch 选项会创建一个 Watcher 实例。
- 依赖收集:
Watcher在初始化时会执行一次getter函数(通常是监听的数据的读取操作),触发数据的getter,从而将当前Watcher添加到依赖列表中。 - 派发更新:当数据变化时,
setter会通知所有依赖的Watcher,触发update方法,最终执行回调函数。
深度监听实现
当设置 deep: true 时,Watcher 会递归遍历监听对象的所有属性,为每个子属性收集依赖。这样,任何嵌套属性的变化都会触发回调。
立即执行选项
如果设置 immediate: true,Watcher 会在创建时立即执行一次回调函数,无需等待数据变化。
异步更新策略
Vue 通过异步队列(nextTick)批量处理 Watcher 更新,避免频繁触发回调。多个数据变化会被合并到一次更新中。
源码关键逻辑(简化)
以下是 Vue 2 中 Watcher 的核心逻辑简化:
class Watcher {
constructor(vm, expOrFn, cb, options) {
this.vm = vm;
this.cb = cb;
this.deep = !!options.deep;
this.getter = parsePath(expOrFn); // 解析路径,返回一个函数
this.value = this.get(); // 首次收集依赖
}
get() {
pushTarget(this); // 将当前 Watcher 设置为全局的依赖目标
const value = this.getter.call(this.vm, this.vm); // 触发数据的 getter
if (this.deep) traverse(value); // 深度监听时递归遍历
popTarget(); // 恢复之前的依赖目标
return value;
}
update() {
queueWatcher(this); // 将 Watcher 加入异步队列
}
run() {
const newValue = this.get();
const oldValue = this.value;
this.value = newValue;
this.cb.call(this.vm, newValue, oldValue); // 执行回调
}
}
Vue 3 的变化
Vue 3 改用 Proxy 实现响应式,但 watch 的核心逻辑类似。watch API 通过 effect 和 scheduler 实现,底层仍依赖依赖收集和派发更新机制。
总结
Vue 的 watch 通过响应式系统和 Watcher 机制实现数据监听。其核心是依赖收集和派发更新,结合异步队列优化性能,并提供深度监听和立即执行等选项。







