vue实现依赖收集
Vue 依赖收集的实现原理
Vue 的依赖收集主要通过响应式系统完成,核心涉及 Observer、Dep 和 Watcher 三个类。以下是具体实现方式:
响应式数据初始化
通过 Object.defineProperty 或 Proxy 对数据对象进行劫持,拦截属性的读取和修改操作。Vue 2.x 使用前者,Vue 3.x 使用后者。

// Vue 2.x 的 defineProperty 实现
function defineReactive(obj, key, val) {
const dep = new Dep() // 每个属性对应一个 Dep 实例
Object.defineProperty(obj, key, {
get() {
if (Dep.target) { // 当前 Watcher 存在时收集依赖
dep.depend()
}
return val
},
set(newVal) {
if (newVal === val) return
val = newVal
dep.notify() // 数据变化时通知更新
}
})
}
Dep 依赖管理器
Dep 类负责管理一组 Watcher,实现依赖的添加和通知。
class Dep {
constructor() {
this.subs = [] // 存储 Watcher 实例
}
depend() {
if (Dep.target) {
Dep.target.addDep(this) // Watcher 记录 Dep
}
}
notify() {
const subs = this.subs.slice()
for (let i = 0; i < subs.length; i++) {
subs[i].update() // 触发 Watcher 更新
}
}
}
Dep.target = null // 静态属性指向当前 Watcher
Watcher 观察者
Watcher 实例在初始化时会触发 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
}
addDep(dep) {
dep.addSub(this) // Dep 记录 Watcher
}
update() {
// 触发组件更新或回调
this.run()
}
}
依赖收集流程
- 组件渲染时创建
Watcher实例,触发get()方法 Dep.target被设置为当前Watcher- 访问数据属性时触发
getter,调用dep.depend() Watcher记录所有关联的Dep,同时Dep记录Watcher- 数据变更时通过
dep.notify()通知所有关联Watcher更新
Vue 3 的改进
Vue 3 改用 Proxy 实现响应式,依赖收集原理类似但更高效:
const reactive = (target) => {
return new Proxy(target, {
get(target, key, receiver) {
track(target, key) // 依赖收集
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
Reflect.set(target, key, value, receiver)
trigger(target, key) // 触发更新
}
})
}
关键区别在于:
- 无需递归遍历对象属性
- 可自动检测新增/删除属性
- 性能更好,尤其对大型对象






