vue数据代理底层实现
Vue 数据代理的底层实现
Vue 的数据代理主要通过 Object.defineProperty 或 Proxy 实现,将 data 对象的属性代理到 Vue 实例上,使得可以直接通过 this.xxx 访问 data 中的属性。
使用 Object.defineProperty 实现
Vue 2.x 使用 Object.defineProperty 实现数据代理。以下是简化后的核心逻辑:
function proxyData(vm, data) {
Object.keys(data).forEach(key => {
Object.defineProperty(vm, key, {
get() {
return data[key];
},
set(newVal) {
data[key] = newVal;
}
});
});
}
- 遍历 data 对象的属性,为每个属性在 Vue 实例上定义 getter 和 setter。
- 访问
this.xxx时,通过 getter 返回data.xxx。 - 修改
this.xxx时,通过 setter 更新data.xxx。
使用 Proxy 实现
Vue 3.x 使用 Proxy 实现数据代理,代码更简洁:
function proxyData(vm, data) {
vm._data = data;
vm = new Proxy(vm, {
get(target, key) {
if (key in target) {
return target[key];
}
return target._data[key];
},
set(target, key, value) {
if (key in target) {
target[key] = value;
} else {
target._data[key] = value;
}
return true;
}
});
return vm;
}
- 通过 Proxy 拦截对 Vue 实例的访问和修改操作。
- 访问
this.xxx时,优先从 Vue 实例自身查找,未找到则从_data中读取。 - 修改
this.xxx时,优先修改 Vue 实例自身属性,否则修改_data中的属性。
与响应式系统的结合
数据代理与响应式系统紧密关联:
- 通过代理访问 data 属性时,会触发响应式系统的依赖收集。
- 修改代理属性时,会触发响应式系统的更新通知。
注意事项
- Vue 2.x 无法检测到对象属性的添加或删除,需使用
Vue.set或Vue.delete。 - Vue 3.x 的 Proxy 可以检测到动态添加的属性,但原始对象仍需用
reactive包装。 - 代理仅针对 data 的顶层属性,嵌套对象需递归处理。







