vue响应式实现机制
Vue 响应式实现机制
Vue 的响应式系统是其核心特性之一,通过数据劫持和依赖收集实现数据变化时自动更新视图。以下是主要实现机制:
数据劫持(Object.defineProperty 或 Proxy)
Vue 2.x 使用 Object.defineProperty 对对象的属性进行劫持,通过 getter 和 setter 拦截属性的访问和修改。当数据被读取时触发 getter 收集依赖,数据被修改时触发 setter 通知更新。
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.x 改用 Proxy 实现,可以拦截整个对象而无需递归遍历属性,且支持数组索引和 length 变化的监听。

const proxy = new Proxy(obj, {
get(target, key) {
console.log('get', key);
return Reflect.get(target, key);
},
set(target, key, value) {
console.log('set', key);
return Reflect.set(target, key, value);
}
});
依赖收集与发布订阅
每个响应式数据会关联一个 Dep(依赖管理器),负责收集当前数据的依赖(Watcher)。当数据被访问时,触发 getter 并将当前 Watcher 存入 Dep 中。
class Dep {
constructor() {
this.subscribers = [];
}
depend() {
if (targetWatcher) {
this.subscribers.push(targetWatcher);
}
}
notify() {
this.subscribers.forEach(watcher => watcher.update());
}
}
Watcher 与更新机制
Watcher 是观察者,代表一个依赖关系。当数据变化时,Dep 会通知所有关联的 Watcher 执行更新(如重新渲染组件)。

class Watcher {
constructor(updateFn) {
this.updateFn = updateFn;
this.update();
}
update() {
targetWatcher = this;
this.updateFn();
targetWatcher = null;
}
}
数组响应式处理
Vue 2.x 通过重写数组的 push、pop 等变异方法实现响应式。这些方法被包裹后会在调用时触发更新通知。
const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);
['push', 'pop', 'shift'].forEach(method => {
const original = arrayProto[method];
arrayMethods[method] = function(...args) {
const result = original.apply(this, args);
dep.notify(); // 触发更新
return result;
};
});
虚拟 DOM 与批量更新
为避免频繁操作真实 DOM,Vue 将变化通过虚拟 DOM 进行 diff 并批量更新。响应式数据变化后,触发组件的 render 函数生成新的虚拟 DOM,通过 diff 算法计算出最小更新路径。
总结
Vue 响应式的核心是通过数据劫持拦截读写操作,结合依赖收集和发布订阅模式实现数据与视图的自动同步。Vue 3 的 Proxy 方案解决了 Vue 2 中对象新增属性和数组处理的局限性,提供了更完善的响应式支持。






