vue实现依赖收集
Vue 依赖收集实现原理
Vue 的依赖收集是通过响应式系统实现的,核心机制基于 Object.defineProperty(Vue 2)或 Proxy(Vue 3)。以下是关键实现步骤:
数据劫持
通过 Object.defineProperty 或 Proxy 拦截数据的读取和修改操作。当组件渲染时访问数据属性,触发 getter 收集依赖;当数据变更时,触发 setter 通知更新。

// Vue 2 实现示例
function defineReactive(obj, key) {
const dep = new Dep(); // 每个属性对应一个 Dep 实例
let val = obj[key];
Object.defineProperty(obj, key, {
get() {
if (Dep.target) { // 当前正在计算的 Watcher
dep.depend(); // 收集依赖
}
return val;
},
set(newVal) {
if (val === newVal) return;
val = newVal;
dep.notify(); // 通知更新
}
});
}
Dep 类
Dep 是依赖管理器,维护一个订阅者列表(subs),负责添加依赖和通知更新。

class Dep {
constructor() {
this.subs = [];
}
depend() {
if (Dep.target) {
this.subs.push(Dep.target);
}
}
notify() {
this.subs.forEach(watcher => watcher.update());
}
}
Dep.target = null; // 静态属性,指向当前 Watcher
Watcher 类
Watcher 是观察者,代表一个依赖。在组件渲染或计算属性求值时创建,通过 get 方法触发数据的 getter 以收集依赖。
class Watcher {
constructor(vm, expOrFn) {
this.vm = vm;
this.getter = parsePath(expOrFn);
this.value = this.get();
}
get() {
Dep.target = this; // 设置当前 Watcher
const value = this.getter.call(this.vm, this.vm);
Dep.target = null; // 收集完成后重置
return value;
}
update() {
this.get(); // 重新求值并触发更新
}
}
依赖收集流程
- 组件初始化:渲染组件时创建
Watcher,执行render函数访问数据。 - 触发 getter:数据属性的
getter被调用,当前Watcher(Dep.target)被添加到Dep的订阅列表。 - 依赖建立:数据属性与
Watcher建立关联,后续数据变化时通过setter触发Dep.notify()。 - 派发更新:
notify调用所有关联Watcher的update方法,重新渲染或计算。
Vue 3 的改进
Vue 3 使用 Proxy 替代 Object.defineProperty,解决了数组和新增属性的监听问题。依赖收集逻辑类似,但通过 track 和 trigger 函数实现:
const proxy = new Proxy(obj, {
get(target, key) {
track(target, key); // 替代 dep.depend()
return Reflect.get(target, key);
},
set(target, key, value) {
Reflect.set(target, key, value);
trigger(target, key); // 替代 dep.notify()
}
});
关键点总结
- 响应式数据:通过劫持数据访问实现自动依赖跟踪。
- 发布-订阅模式:
Dep管理依赖,Watcher作为订阅者。 - 动态更新:数据变化时精确通知相关依赖,避免不必要的渲染。






