vue如何实现响应式
Vue 响应式原理
Vue 的响应式系统基于 JavaScript 的 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) {
console.log(`修改 ${key} 为 ${newVal}`);
val = newVal;
}
});
}
在 Vue 3 中,改用 Proxy 代理整个对象,可以更高效地监听动态添加的属性。
const reactive = (obj) => {
return new Proxy(obj, {
get(target, key) {
console.log(`访问 ${key}`);
return target[key];
},
set(target, key, value) {
console.log(`修改 ${key} 为 ${value}`);
target[key] = value;
return true;
}
});
};
依赖收集
每个响应式属性关联一个 Dep(依赖管理器),用于存储依赖该属性的 Watcher(订阅者)。当属性被访问时,当前 Watcher 会被添加到 Dep 中;当属性被修改时,Dep 会通知所有 Watcher 更新。

class Dep {
constructor() {
this.subscribers = [];
}
depend() {
if (target && !this.subscribers.includes(target)) {
this.subscribers.push(target);
}
}
notify() {
this.subscribers.forEach(sub => sub());
}
}
虚拟 DOM 与更新
当数据变化时,Vue 会生成新的虚拟 DOM,并通过 diff 算法对比新旧虚拟 DOM,最终高效地更新真实 DOM。
实现响应式的注意事项
- 对象属性:Vue 2 中直接添加新属性不会触发响应式,需使用
Vue.set或this.$set。 - 数组变更:直接通过索引修改数组或修改长度不会触发响应式,需使用数组的变异方法(如
push、pop)或Vue.set。 - 深层监听:嵌套对象需要递归劫持才能实现深层响应式。
Vue 3 的优化
Vue 3 使用 Proxy 替代 Object.defineProperty,解决了以下问题:
- 直接监听动态添加的属性。
- 无需递归劫持即可实现深层响应式。
- 性能更高,尤其在处理大型对象或数组时。






