vue3.x之响应式原理Proxy
前面在介绍vue2的响应式原理中,我们已经介绍过vue数据响应式原理是通过数据劫持结合发布订阅者模式来实现的。其中在vue2中数据劫持是通过Object.defineProperty()来实现的,其中存在的问题是:
1. 新增、删除对象属性,视图不会更新
2. 通过下标修改数组,视图不会更新
vue2响应式原理可以参考另一篇文章vue2.x之数据绑定和响应式原理
Proxy
在vue3中使用Proxy来进行代理拦截,在拦截的时候有get,set,和deleteProperty
- get: 读取p的某个属性时调用
- set: 修改、增加p的某个属性时调用
- deleteProperty: 删除p的某个属性时调用
let person = { name:"张三", age:18 }; const p = new Proxy(person,{ //读取p的某个属性时调用 get(target, propName) { console.log(`有人读取了p身上的${propName}属性`); return target[propName]; }, //修改、增加p的某个属性时调用 set(target, propName, value) { console.log(`有人修改了p身上的${propName}`); target[propName] = value; }, //删除p的某个属性时调用 deleteProperty(target, propName) { console.log(`有人删除了p身上的${propName}`); return delete target[propName]; } });
⏰ 修改p对象
p.name;
p.age = 20; p.sex = '女';
delete p.sex;
console.log(p);
console.log(person);
⏰ 效果如下

可以看出来,上面vue2中存在的问题确实不存在了。
Reflect
在vue3内部,不仅通过proxy进行代理,而且还通过Reflect(反射)对源对象的属性进行操作,Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。
Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。通过修改某些Object方法的返回结果,让其变得更规范化。如Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)则会返回false。
因此上面的代码还可以写成这种
let person = { name:"张三", age:18 }; const p = new Proxy(person,{ //读取p的某个属性时调用 get(target, propName) { console.log(`有人读取了p身上的${propName}属性`); return Reflect.get(target, propName); }, //修改、增加p的某个属性时调用 set(target, propName, value) { console.log(`有人修改了p身上的${propName}`); Reflect.set(target, propName, value); }, //删除p的某个属性时调用 deleteProperty(target, propName) { console.log(`有人删除了p身上的${propName}`); return Reflect.deleteProperty(target, propName); } });
⏰ 修改p对象
p.name;
p.age = 20; p.sex = '女';
delete p.sex;
console.log(p);
console.log(person);
⏰ 效果如下

浙公网安备 33010602011771号