vue实现数据劫持
Vue 数据劫持的实现原理
Vue 的数据劫持主要通过 Object.defineProperty 或 Proxy 实现,用于监听数据变化并触发视图更新。以下是具体实现方式:
使用 Object.defineProperty
Object.defineProperty 是 Vue 2.x 的核心实现方式,通过劫持对象的属性实现响应式。
function defineReactive(obj, key, val) {
// 递归处理嵌套对象
observe(val);
Object.defineProperty(obj, key, {
get() {
console.log(`读取 ${key}: ${val}`);
return val;
},
set(newVal) {
if (newVal !== val) {
console.log(`设置 ${key} 为 ${newVal}`);
val = newVal;
// 触发更新
updateView();
}
}
});
}
function observe(obj) {
if (typeof obj !== 'object' || obj === null) {
return;
}
Object.keys(obj).forEach(key => {
defineReactive(obj, key, obj[key]);
});
}
function updateView() {
console.log('视图更新');
}
// 测试
const data = { name: 'Vue' };
observe(data);
data.name = 'React'; // 输出: 设置 name 为 React, 视图更新
使用 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, newVal) {
if (target[key] !== newVal) {
console.log(`设置 ${key} 为 ${newVal}`);
target[key] = newVal;
updateView();
}
return true;
}
});
}
function updateView() {
console.log('视图更新');
}
// 测试
const data = reactive({ name: 'Vue' });
data.name = 'React'; // 输出: 设置 name 为 React, 视图更新
对比与注意事项
-
Object.defineProperty局限性
无法监听新增/删除属性(需使用Vue.set/Vue.delete),对数组需特殊处理(重写数组方法)。 -
Proxy优势
支持监听整个对象,包括新增/删除属性,无需特殊处理数组,性能更好。
-
性能优化
避免频繁触发更新,可通过异步更新队列(如 Vue 的nextTick)合并多次操作。
实际应用示例
在 Vue 组件中,数据劫持自动完成:
export default {
data() {
return { message: 'Hello' };
},
methods: {
changeMessage() {
this.message = 'Updated'; // 触发视图更新
}
}
};






