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);

⏰ 效果如下

posted on 2024-07-11 19:19  梁飞宇  阅读(38)  评论(0)    收藏  举报