vue 实现响应式底层
Vue 响应式原理的核心机制
Vue 的响应式系统基于 ES5 的 Object.defineProperty(Vue 2)或 ES6 的 Proxy(Vue 3)实现。以下是核心实现逻辑:
数据劫持
通过拦截对象属性的读取和修改操作,在 getter 中收集依赖,在 setter 中触发更新。对于数组,Vue 重写了数组的变异方法(如 push/pop/splice)。

// Vue 2 的简化实现
function defineReactive(obj, key) {
const dep = new Dep()
let val = obj[key]
Object.defineProperty(obj, key, {
get() {
dep.depend() // 收集当前正在计算的 Watcher
return val
},
set(newVal) {
if (newVal === val) return
val = newVal
dep.notify() // 通知所有订阅者更新
}
})
}
依赖收集
每个响应式属性关联一个 Dep 实例,用于管理所有订阅该属性的 Watcher。当属性被访问时,当前执行的 Watcher 会被添加到依赖列表中。
class Dep {
constructor() {
this.subscribers = new Set()
}
depend() {
if (activeWatcher) {
this.subscribers.add(activeWatcher)
}
}
notify() {
this.subscribers.forEach(watcher => watcher.update())
}
}
派发更新
当数据变化时,通过 Dep 通知所有 Watcher 执行更新。组件级的 Watcher 会触发重新渲染,计算属性的 Watcher 会重新计算值。

Vue 3 的 Proxy 改进
Vue 3 使用 Proxy 替代 Object.defineProperty,解决了以下问题:
- 可检测新增/删除的属性
- 更好的数组变化检测
- 减少递归遍历的性能消耗
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
track(target, key)
return Reflect.get(target, key)
},
set(target, key, value) {
Reflect.set(target, key, value)
trigger(target, key)
}
})
}
异步更新队列
Vue 通过异步队列优化多次数据变更的更新效率。同一事件循环内的所有数据变更会合并为一次更新,使用 nextTick 实现延迟执行。
queueWatcher(watcher) {
if (!flushing) {
queue.push(watcher)
}
nextTick(flushSchedulerQueue)
}






