vue怎样实现响应式
Vue 响应式实现原理
Vue 的响应式系统基于 ES5 的 Object.defineProperty(Vue 2.x)或 ES6 的 Proxy(Vue 3.x)实现,通过数据劫持结合发布-订阅模式来追踪数据变化并触发视图更新。
Vue 2.x 实现方式
核心机制:
- 使用
Object.defineProperty递归劫持对象的属性,将其转为getter/setter。 - 每个组件实例对应一个
Watcher实例,负责依赖收集和派发更新。
具体实现步骤:
-
数据劫持:
function defineReactive(obj, key, val) { Object.defineProperty(obj, key, { get() { console.log('读取属性', key); return val; }, set(newVal) { if (newVal !== val) { console.log('更新属性', key); val = newVal; } } }); } -
依赖收集:
- 在
getter中通过Dep类收集当前正在执行的Watcher。 Dep.target指向当前Watcher,调用dep.depend()建立依赖关系。
- 在
-
派发更新:
- 在
setter中通过dep.notify()通知所有订阅的Watcher更新视图。
- 在
数组处理:

- 重写数组的
push、pop等变异方法,在调用时手动触发更新。 - 通过
__proto__或直接覆盖原型链实现。
Vue 3.x 实现方式
核心改进:
- 使用
Proxy替代Object.defineProperty,支持动态新增属性和数组索引的直接修改。 - 引入
Reflect操作对象,避免直接操作原对象。
具体实现步骤:
-
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; } }); }; -
依赖管理:

- 通过
track函数建立target -> key -> effect的映射关系。 - 使用
WeakMap存储依赖,避免内存泄漏。
- 通过
-
响应式 API:
reactive:深度代理对象。ref:包装基本类型为{ value }对象,通过.value访问。computed和watch基于effect实现。
手动实现简单响应式
以下是一个简化版的响应式实现示例:
class Dep {
constructor() {
this.subscribers = new Set();
}
depend() {
if (Dep.target) this.subscribers.add(Dep.target);
}
notify() {
this.subscribers.forEach(sub => sub());
}
}
function observe(obj) {
Object.keys(obj).forEach(key => {
let value = obj[key];
const dep = new Dep();
Object.defineProperty(obj, key, {
get() {
dep.depend();
return value;
},
set(newVal) {
value = newVal;
dep.notify();
}
});
});
}
function autorun(callback) {
Dep.target = callback;
callback();
Dep.target = null;
}
注意事项
-
性能优化:
- Vue 2.x 中嵌套层级过深会影响初始化性能。
- Vue 3.x 的
Proxy性能更优,但需注意浏览器兼容性。
-
局限性:
- Vue 2.x 无法检测到对象属性的添加或删除(需用
Vue.set/Vue.delete)。 - Vue 3.x 的
Proxy不支持 IE11。
- Vue 2.x 无法检测到对象属性的添加或删除(需用
-
开发建议:
- 复杂逻辑使用
computed缓存计算结果。 - 避免在模板中直接使用复杂表达式,优先用
methods或computed。
- 复杂逻辑使用






