vue响应式实现机制
Vue 响应式实现机制
Vue 的响应式系统通过数据劫持和依赖收集实现,核心基于 Object.defineProperty(Vue 2)或 Proxy(Vue 3)。以下是具体实现机制:
数据劫持
Vue 2 使用 Object.defineProperty 劫持对象的属性访问和修改。通过定义 getter 和 setter,在属性被访问或修改时触发依赖更新。

// Vue 2 数据劫持简化示例
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
console.log('get', key);
return val;
},
set(newVal) {
if (newVal !== val) {
console.log('set', key);
val = newVal;
}
}
});
}
Vue 3 改用 Proxy 代理整个对象,能直接监听对象增删和数组变化,无需递归遍历属性。
// Vue 3 Proxy 示例
const reactive = (target) => {
return new Proxy(target, {
get(target, key, receiver) {
console.log('get', key);
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
console.log('set', key);
return Reflect.set(target, key, value, receiver);
}
});
};
依赖收集
每个响应式数据关联一个 Dep 实例(依赖管理器),在 getter 中收集当前正在执行的 Watcher(依赖),在 setter 中通知所有 Watcher 更新。

class Dep {
constructor() {
this.subscribers = new Set();
}
depend() {
if (activeWatcher) this.subscribers.add(activeWatcher);
}
notify() {
this.subscribers.forEach(watcher => watcher.update());
}
}
let activeWatcher = null;
class Watcher {
constructor(updateFn) {
this.updateFn = updateFn;
this.update();
}
update() {
activeWatcher = this;
this.updateFn();
activeWatcher = null;
}
}
虚拟 DOM 与批量更新
数据变化触发 Watcher 更新后,Vue 通过异步队列(nextTick)批量处理 DOM 更新,避免重复渲染。虚拟 DOM 差异比对(diff 算法)最小化真实 DOM 操作。
数组响应式处理
Vue 2 通过重写数组的 push、pop 等方法实现响应式,内部调用 ob.dep.notify() 通知更新。Vue 3 的 Proxy 可直接监听数组索引变化。
// Vue 2 数组劫持示例
const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);
['push', 'pop'].forEach(method => {
const original = arrayProto[method];
arrayMethods[method] = function(...args) {
const result = original.apply(this, args);
this.__ob__.dep.notify();
return result;
};
});
总结
- Vue 2:基于
Object.defineProperty+Dep/Watcher,需递归遍历对象且对数组特殊处理。 - Vue 3:基于
Proxy+effect(类似Watcher),支持原生对象和数组操作,性能更优。






