vue2响应式原理
vue2使用Object.defineProperty()对数据进行劫持,只能捕获到读取属性和修改属性的操作,无法捕获到添加属性和删除属性的操作。
具体代码:
// 源数据
const _data = {
a:"aaa",
b:"bbb"
}
// 创建一个空对象
const data = {
}
// 使用 Object.defineProperty()对数据进行劫持,
// 传入三个参数,第一个是代理对象,第二个代理对象的属性,第三个是一个配置对象,包含get、set函数
Object.defineProperty(data, "a", {
// 当读取data中的a属性时,调用此函数
get(){
console.log("有人读取了data中的a属性");
return _data.a;
},
// 当修改data中的a属性时,调用此函数,参数为修改的值
set(val){
console.log("有人修改了data中的a属性");
_data.a = val;
}
})
// 属性b同理
Object.defineProperty(data, "b", {
// 当读取data中的b属性时,调用此函数
get(){
console.log("有人读取了data中的b属性");
return _data.b;
},
// 当修改data中的b属性时,调用此函数,参数为修改的值
set(val){
console.log("有人修改了data中的b属性");
_data.b = val;
}
})
vue3响应式原理
vue3与vue2不同,vue3使用proxy和reflect对数据进行劫持和代理,既能捕获到读取属性和修改属性的操作,也可以捕获到添加属性和删除属性的操作。
具体代码:
// 源数据
const _data = {
a: "aaa",
b: "bbb"
}
// 使用 Proxy、Reflect对数据进行代理和劫持,
// 传入两个参数,第一个是代理对象,第二个是一个配置对象,包含get、set、deleteProperty函数
const data = new Proxy(_data, {
// 当读取某个属性时,调用此函数,第一个参数为代理的目标对象,第二个参数为读取的属性
get(target, property) {
// 通过Reflect获取目标对象的属性
console.log(`有人读取了data中的${property}属性`);
// 通过Reflect获取目标对象的属性
return Reflect.get(target, property);
},
// 当修改和添加某个属性时,调用此函数,第一个参数为代理的目标对象,第二个参数为要修改或添加的属性,第三个参数为修改或添加的值
set(target, property, val) {
console.log(`有人修改了data中的${property}属性`);
// 通过Reflect修改或添加目标对象的属性
Reflect.set(target, property, val);
},
// 当删除某个属性时,调用此函数,第一个参数为代理的目标对象,第二个参数为要删除的属性
deleteProperty(target, property) {
console.log(`有人删除了data中的${property}属性`);
// 通过Reflect删除目标对象的属性
return Reflect.deleteProperty(target, property);
}
})