vue数据代理底层实现
Vue 数据代理的底层实现
Vue 的数据代理主要通过 Object.defineProperty 或 Proxy 实现,将数据对象的属性代理到 Vue 实例上,从而实现响应式数据绑定。

使用 Object.defineProperty 实现数据代理
Vue 2.x 使用 Object.defineProperty 对数据进行劫持,通过 getter 和 setter 实现数据代理。
function observe(data) {
if (!data || typeof data !== 'object') return;
Object.keys(data).forEach(key => {
defineReactive(data, key, data[key]);
});
}
function defineReactive(obj, key, val) {
observe(val); // 递归处理嵌套对象
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get() {
console.log(`获取 ${key}: ${val}`);
return val;
},
set(newVal) {
if (newVal === val) return;
console.log(`设置 ${key}: ${newVal}`);
val = newVal;
observe(newVal); // 对新值进行响应式处理
}
});
}
const data = { name: 'Vue' };
observe(data);
data.name; // 触发 getter
data.name = 'React'; // 触发 setter
使用 Proxy 实现数据代理
Vue 3.x 使用 Proxy 替代 Object.defineProperty,提供了更强大的数据代理能力。
function reactive(data) {
if (!data || typeof data !== 'object') return data;
const handler = {
get(target, key, receiver) {
console.log(`获取 ${key}`);
const result = Reflect.get(target, key, receiver);
return reactive(result); // 递归代理嵌套对象
},
set(target, key, value, receiver) {
if (value === target[key]) return true;
console.log(`设置 ${key}: ${value}`);
return Reflect.set(target, key, value, receiver);
}
};
return new Proxy(data, handler);
}
const data = reactive({ name: 'Vue' });
data.name; // 触发 get
data.name = 'React'; // 触发 set
数据代理的核心流程
- 初始化阶段:Vue 实例化时,遍历
data对象的属性,通过Object.defineProperty或Proxy将其代理到实例上。 - 依赖收集:在 getter 中收集依赖(Watcher),在 setter 中通知依赖更新。
- 递归代理:对嵌套对象进行递归代理,确保深层属性也是响应式的。
- 数组处理:Vue 2.x 中对数组方法(如
push、pop)进行重写以实现响应式。
注意事项
Object.defineProperty无法检测到对象属性的添加或删除,Vue 提供了Vue.set和Vue.delete方法解决这一问题。Proxy可以监听整个对象,无需单独处理每个属性,且支持数组索引和length变化的监听。- Vue 3.x 的
Proxy实现性能更好,但兼容性较差(不支持 IE11)。







