vue数据拦截怎么实现
Vue 数据拦截的实现方式
Vue 的数据拦截主要通过 Object.defineProperty 或 Proxy 实现,用于监听数据变化并触发视图更新。

使用 Object.defineProperty
Vue 2.x 采用 Object.defineProperty 对对象的属性进行劫持。这种方式需要对对象的每个属性递归地设置 getter 和 setter。

function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
console.log(`读取 ${key}: ${val}`);
return val;
},
set(newVal) {
if (newVal !== val) {
console.log(`设置 ${key}: ${newVal}`);
val = newVal;
}
}
});
}
const data = { name: 'Vue' };
defineReactive(data, 'name', data.name);
data.name = 'React'; // 触发 setter
console.log(data.name); // 触发 getter
使用 Proxy
Vue 3.x 改用 Proxy 实现数据拦截,能直接监听整个对象而非逐个属性,且支持数组和动态新增属性。
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
console.log(`读取 ${key}: ${target[key]}`);
return target[key];
},
set(target, key, value) {
if (target[key] !== value) {
console.log(`设置 ${key}: ${value}`);
target[key] = value;
}
return true;
}
});
}
const data = reactive({ name: 'Vue' });
data.name = 'React'; // 触发 set
console.log(data.name); // 触发 get
数组拦截的特殊处理
Vue 2.x 中需对数组方法(如 push、pop)进行重写以实现拦截:
const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);
['push', 'pop', 'shift'].forEach(method => {
const original = arrayProto[method];
arrayMethods[method] = function(...args) {
console.log(`数组操作: ${method}`);
return original.apply(this, args);
};
});
const arr = [];
arr.__proto__ = arrayMethods;
arr.push(1); // 输出 "数组操作: push"
对比与选择
Object.defineProperty:兼容性好,但无法监听新增属性,需手动调用Vue.set。Proxy:功能更强大,支持监听整个对象和数组,但需环境支持 ES6。
实际开发中,Vue 3.x 推荐使用 Proxy,而 Vue 2.x 项目仍需依赖 Object.defineProperty。






