Vue数据依赖实现
Vue数据依赖实现原理
Vue的数据依赖实现基于响应式系统,核心是通过Object.defineProperty或Proxy拦截数据变化,结合发布-订阅模式实现依赖收集和更新触发。
核心机制
依赖收集
每个响应式数据属性会关联一个Dep实例,用于存储所有依赖该属性的Watcher。当属性被访问时,当前Watcher会被添加到Dep中。

触发更新
当属性值变化时,Dep会通知所有关联的Watcher执行更新操作。这个过程通过setter拦截实现,确保数据变化时视图能同步更新。
实现代码示例
// Dep类实现
class Dep {
constructor() {
this.subscribers = new Set()
}
depend() {
if (activeWatcher) {
this.subscribers.add(activeWatcher)
}
}
notify() {
this.subscribers.forEach(watcher => watcher.update())
}
}
// Watcher类实现
class Watcher {
constructor(updateFn) {
this.updateFn = updateFn
this.update()
}
update() {
activeWatcher = this
this.updateFn()
activeWatcher = null
}
}
// 响应式转换
function reactive(obj) {
Object.keys(obj).forEach(key => {
const dep = new Dep()
let value = obj[key]
Object.defineProperty(obj, key, {
get() {
dep.depend()
return value
},
set(newVal) {
value = newVal
dep.notify()
}
})
})
return obj
}
数组处理
Vue对数组方法进行了特殊处理,通过重写push、pop等变异方法来实现响应式:

const arrayProto = Array.prototype
const arrayMethods = Object.create(arrayProto)
const methodsToPatch = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse']
methodsToPatch.forEach(method => {
const original = arrayProto[method]
arrayMethods[method] = function(...args) {
const result = original.apply(this, args)
const ob = this.__ob__
ob.dep.notify()
return result
}
})
现代实现方式
Vue 3改用Proxy实现响应式,解决了Object.defineProperty的局限性:
function 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)
return true
}
})
}
性能优化
响应式系统通过以下方式优化性能:
- 异步更新队列合并多次数据变更
- 组件级更新避免不必要的DOM操作
- 依赖追踪确保只更新必要的组件
这种实现方式使得Vue能够在数据变化时高效地更新视图,同时保持开发者的心智模型简单直观。






