vue依赖收集的实现
Vue 依赖收集的实现原理
Vue 的依赖收集是通过响应式系统实现的,核心在于 Observer、Dep 和 Watcher 三者的协作。
响应式数据初始化
通过 Object.defineProperty 或 Proxy(Vue 3)劫持数据对象的属性访问。在 getter 中触发依赖收集,在 setter 中触发更新通知。

function defineReactive(obj, key, val) {
const dep = new Dep();
Object.defineProperty(obj, key, {
get() {
if (Dep.target) {
dep.depend(); // 收集依赖
}
return val;
},
set(newVal) {
if (val === newVal) return;
val = newVal;
dep.notify(); // 触发更新
}
});
}
Dep 类管理依赖
Dep 是依赖管理器,每个响应式属性对应一个 Dep 实例,用于存储所有依赖该属性的 Watcher。

class Dep {
constructor() {
this.subs = []; // 存储 Watcher 实例
}
depend() {
if (Dep.target) {
this.subs.push(Dep.target); // 添加 Watcher
}
}
notify() {
this.subs.forEach(watcher => watcher.update()); // 通知更新
}
}
Dep.target = null; // 全局唯一 Watcher 标记
Watcher 类触发依赖
Watcher 是观察者,在组件渲染或计算属性求值时被创建。它会将自身赋值给 Dep.target,触发属性的 getter 从而完成依赖收集。
class Watcher {
constructor(vm, expOrFn, cb) {
this.vm = vm;
this.getter = parsePath(expOrFn);
this.cb = cb;
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() {
this.run();
}
run() {
const value = this.get();
if (value !== this.value) {
this.cb.call(this.vm, value, this.value);
}
}
}
依赖收集流程
- 组件初始化时创建
Watcher,触发get方法。 Dep.target被设置为当前Watcher。- 访问响应式数据时触发
getter,调用dep.depend()将Watcher存入subs。 - 数据变化时触发
setter,调用dep.notify()通知所有Watcher更新。
Vue 3 的优化
Vue 3 改用 Proxy 实现响应式,依赖收集逻辑类似但更高效:
- 通过
track函数收集依赖(对应depend)。 - 通过
trigger函数触发更新(对应notify)。 - 使用
WeakMap和Set存储依赖关系,避免内存泄漏。






