• Vue3 数据响应式原理:Proxy和Reflect


    我们在Vue2中使用的是Object.defineProperty方法来实现数据响应式的,可以通过get和set方法来监听对象的访问和修改。

    但是并不能响应对象中属性的增加和删除,只能使用Vue.$set 和Vue.$delete 来对对象中的属性进行增加和删除。

    数组也不能直接通过下标来对数组进行修改,只能使用Vue封装过的数组方法来实现数组的响应式

    以上问题在Vue3中就不会存在,因为其使用的是Proxy代理。

    一、Proxy

    Proxy和Object.defineProperty的作用类似,不过在使用上更加便捷。

    (一)创建Proxy代理

    如果我们先想要创建一个Proxy代理,就需要使用new 关键字:

    let 代理对象 = new Proxy(源对象, {  // 配置项  })

    如,我们对Person对象进行Proxy代理: 

    1. let person = {
    2. name:"张三",
    3. age:18
    4. }
    5. let P = new Proxy(person, {});

    代理完成后,我们在P中修改name属性,person的属性也会被修改,这就完成了数据代理。 

     

    (二)Proxy配置项

    以上我们只是实现了代理,但是还没有实现响应式,无法捕获到数据的增删改查。

    我们只需要添加配置项即可:

    读取数据:get (target, prop) {  // 响应  }

    修改和添加数据:set (target, prop, value) {  // 响应  }

    删除数据:deleteProperty (target, prop) {  // 响应  }

    1. let P = new Proxy(person, {
    2. // 读取属性
    3. get(target, prop) {
    4. console.log(`读取了P的${prop}属性`);
    5. },
    6. // 修改和增加属性
    7. set(target, prop, value) {
    8. console.log(`修改或新增了P的${prop}属性,值为${value}`);
    9. },
    10. // 删除属性
    11. deleteProperty(target, prop) {
    12. console.log(`删除了P的${prop}属性`);
    13. }
    14. });

    现在我们对代理对象进行属性的增删改查都会触发响应式。 

    还没完,代理对象中的数据变化了,但是还没引起源对象的变化,我们将上面的代码完善一下即可:

    1. let P = new Proxy(person, {
    2. // 读取属性
    3. get(target, prop) {
    4. return target[prop];
    5. },
    6. // 修改和增加属性
    7. set(target, prop, value) {
    8. target[prop] = value;
    9. },
    10. // 删除属性
    11. deleteProperty(target, prop) {
    12. return delete target[prop]
    13. }
    14. });

    这下我们就能完成响应式了。 

    二、Reflect

     reflect的作用就是对源对象中的属性进行操作。

    读取数据:Reflect.get (源对象, 属性名)

    修改或新增数据:Reflect.get (源对象, 属性名, 属性值)

    删除属性:Reflect.deleteProperty (源对象, 属性名)

    所以,我们就可以将上面的代码改为如下代码:

    1. let P = new Proxy(person, {
    2. // 读取属性
    3. get(target, prop) {
    4. return Reflect.get(target, prop);
    5. },
    6. // 修改和增加属性
    7. set(target, prop, value) {
    8. return Reflect.set(target, prop, value);
    9. },
    10. // 删除属性
    11. deleteProperty(target, prop) {
    12. return Reflect.deleteProperty(target, prop);
    13. }
    14. });

    Vue3的源码底层实现就是使用的Proxy + Reflect 实现的。

    使用Reflect主要是能够方便代码进行书写,使用Reflect 即使是语法错误,都会继续执行,不需要使用繁琐的try catch 捕获后继续执行。

  • 相关阅读:
    微信小程序测试策略和注意事项?
    软件测试所有测试方法
    springboot+shiro+layuimini实现后台管理系统的权限控制(一)基础环境搭建
    如何为 SAST 工具设置误报基准?
    Redis的Set类型、Sorted Set类型、Bitmap类型和HyperLogLog
    分析性质题(集合类):CF1371F
    不受约束的bimap双图的测试程序
    Mybatis IFNULL函数用法
    HoloLens联合发明人:打造理想的全天AR需要解决这些问题
    wps/word 如何让表格的标题和表格名称文本(表1-1 xxx)跨页显示(已解决)
  • 原文地址:https://blog.csdn.net/XunLin233/article/details/134374402