vue watch的实现原理
Vue 中 watch 的实现原理
Vue 的 watch 功能基于响应式系统,通过监听数据变化并触发回调函数实现。以下是其核心实现原理:

响应式依赖收集
Vue 的响应式系统通过 Object.defineProperty 或 Proxy 拦截数据的读写操作。当在 watch 中监听一个属性时,Vue 会将该属性添加到依赖列表中,并在属性变化时通知所有依赖的观察者。

// 简化版响应式实现
function defineReactive(obj, key, val) {
const dep = new Dep(); // 依赖管理器
Object.defineProperty(obj, key, {
get() {
if (Dep.target) {
dep.addSub(Dep.target); // 收集依赖
}
return val;
},
set(newVal) {
if (newVal === val) return;
val = newVal;
dep.notify(); // 触发更新
}
});
}
Watcher 的创建与调度
watch 的每个监听项会创建一个 Watcher 实例。当监听的数据变化时,Watcher 会执行回调函数。
class Watcher {
constructor(vm, expOrFn, cb) {
this.vm = vm;
this.cb = cb;
this.getter = parsePath(expOrFn); // 解析属性路径
this.value = this.get(); // 触发依赖收集
}
get() {
Dep.target = this; // 标记当前 Watcher
const value = this.getter.call(this.vm, this.vm); // 触发 getter
Dep.target = null; // 重置
return value;
}
update() {
const oldValue = this.value;
this.value = this.get(); // 获取新值
this.cb.call(this.vm, this.value, oldValue); // 执行回调
}
}
深层监听与立即执行
- 深层监听(deep):通过递归遍历对象的所有属性,为每个子属性添加
Watcher。 - 立即执行(immediate):在
Watcher初始化时直接调用回调函数。
if (options.immediate) {
cb.call(vm, watcher.value);
}
if (options.deep) {
traverse(value); // 递归触发子属性的 getter
}
异步更新队列
Vue 通过异步队列(如 Promise.then 或 setTimeout)批量处理 Watcher 的更新,避免频繁触发回调。
function queueWatcher(watcher) {
queue.push(watcher);
nextTick(flushSchedulerQueue); // 异步执行更新
}
总结
- 依赖收集:通过响应式系统的
getter收集Watcher依赖。 - 触发更新:数据变化时通过
setter通知Watcher执行回调。 - 异步优化:使用队列机制合并多次更新,提升性能。
- 扩展功能:支持
deep和immediate等配置项。
通过以上机制,watch 实现了高效、灵活的数据监听功能。






