vue 响应式实现
Vue 响应式实现原理
Vue 的响应式系统通过数据劫持和依赖收集实现,核心基于 Object.defineProperty(Vue 2)或 Proxy(Vue 3)。以下是关键实现机制:

数据劫持
Vue 2 使用 Object.defineProperty 递归遍历对象的属性,将其转换为 getter/setter:

function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
console.log('读取属性', key);
return val;
},
set(newVal) {
if (newVal === val) return;
console.log('更新属性', key);
val = newVal;
}
});
}
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); // 触发更新
return true;
}
});
};
依赖收集与派发更新
- 依赖收集:在 getter 中通过
Dep类和Watcher建立关联,模板编译时每个表达式会创建一个Watcher。 - 派发更新:setter 触发时通知所有关联的
Watcher执行更新。
数组处理
Vue 2 对数组方法(如 push/pop)进行重写:
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);
dep.notify(); // 手动触发更新
return result;
};
});
响应式 API 对比
| 特性 | Vue 2 (Object.defineProperty) | Vue 3 (Proxy) |
|---|---|---|
| 检测范围 | 仅属性级别 | 对象/数组全量监听 |
| 性能 | 递归初始化成本高 | 惰性监听更高效 |
| 数组支持 | 需特殊处理 | 原生支持 |
| 新增属性 | 需 Vue.set |
直接响应 |
实现注意事项
- 避免循环引用导致栈溢出,可通过
WeakMap缓存已处理对象。 - 嵌套对象需要递归劫持,Vue 3 的
Proxy可动态处理深层属性。 - 对于大规模数据,考虑使用
shallowReactive避免深度监听开销。
通过上述机制,Vue 实现了数据变化到视图更新的自动化绑定,开发者只需关注数据逻辑而非 DOM 操作。






