ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

浅析ref和reactive/toRefs响应式原理及reactive创建的响应式对象解构后为什么会失去响应式的原因分析

2021-10-27 22:33:13  阅读:183  来源: 互联网

标签:target 响应 解构 reactive Proxy key 浅析


一、reactive 创建的响应式对象解构后为什么会失去响应式

  Vue 拥有一个响应式系统,可以让它在数据更新的时候自动进行视图的更新。在Vue3.0中,可以使用 reactive 声明响应式状态。文档说不要解构 reactive 创建的响应式对象,为什么?因为会失去响应式的功能,那为什么会失去,我们就来简单研究下。

1、进入reactive方法:

  可以看到它在内部调用了createReactiveObject方法,这名字很好理解就是创建响应式对象,调试进去:

  它在这里做了一些处理,细节暂时不探究,重点在这:

  创建了一个代理对象将其保存在内部并返回,学习Vue3或多或少都听过Vue3如何进行数据视图更新的,Proxy对数据进行了拦截,当数据发生变化,通知Vue进行视图变化。

  可以看出 reactive 方法其实就是创建了一个Proxy对象,以及进行了一系列处理,其中并没有找到它可能会失去响应式的情况,也就是说它失去响应式不在于Vue而是在于Proxy对象本身,那么可以简化一下。

2、Proxy 解构

(1)Proxy 解构基本对象

const obj = {
  count: 1
};
const proxy = new Proxy(obj, {
  get(target, key, receiver) {
    console.log("这里是get");
    return Reflect.get(target, key, receiver);
  },
  set(target, key, value, receiver) {
    console.log("这里是set");
    return Reflect.set(target, key, value, receiver);
  }
});

  我们可以看到不解构的话,count 赋值 2 可以做到响应式更改。而解构赋值,count 就是 5 ,proxy 还是 { count: 2 }

  是因为解构相当于重新赋值给另一个变量的原因吗,也就是说它变成了一个新值。

(2)Proxy 解构嵌套对象:我们再看下嵌套对象

const obj = {
    a: {
        count: 1
    }
};
function reactive(obj) {
    return new Proxy(obj, {
        get(target, key, receiver) {
            console.log("这里是get");
            if (typeof target[key] === "object") {
                return reactive(target[key]);
            };
            return Reflect.get(target, key, receiver);
        },
        set(target, key, value, receiver) {
            console.log("这里是set");
            return Reflect.set(target, key, value, receiver);
        }
    });
};
const proxy = reactive(obj);

(1)直接赋值:proxy 有响应变化

(2)解构一次:proxy 也有响应变化

(3)解构2次到底:proxy 不再响应变化

(4)总结原因:为什么会不同,其实很好理解,只解构一次,其实新的对象的 count 仍然是被代理的

  而解构两次,直接获取了count,相当于绕过了代理 a,直接拿到基本类型的值。

  那么就很好理解了,解构为什么会失去响应,用这个图就可以解释:
在这里插入图片描述

  因为解构赋值相当于直接跳过了代理那一层,在下面直接获取值,所以 get 和 set 无法被调用

二、ref 和 reactive + toRefs 响应式实现原理

  对于基本数据类型,函数传递或者对象解构时,会丢失原始数据的引用。换言之,我们没法让基本数据类型,或者解构后的变量(如果它的值也是基本数据类型的话),成为响应式的数据。

  我们没办法让 a 或 x 这样的基本数据类型成为响应式的数据的,Proxy 也无法劫持基本数据。

  但是有时候,我们确实就是想一个数字、一个字符串是响应式的,或者就是想利用解构的写法。那怎么办呢?只能通过创建一个对象,也即是源码中的 Ref 数据,然后将原始数据保存在 Ref 的属性value当中,再将它的引用返回给使用者

  既然是我们自己创造出来的对象,也就没必要使用 Proxy 再做代理了,直接劫持这个 value 的 get/set 即可,这就是 ref 函数与 Ref 类型的由来。

  不过单靠 ref 还没法解决对象解构的问题,它只是将基本数据保持在一个对象的 value 中,以实现数据响应式。对于对象的解构还需要另外一个函数:toRefs。通过遍历对象,将每个属性值都转成 Ref 数据,这样解构出来的还是 Ref 数据,自然就保持了响应式数据的引用。

标签:target,响应,解构,reactive,Proxy,key,浅析
来源: https://www.cnblogs.com/goloving/p/15473372.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有