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

自从专注于React之后,已经有段时间没有用过Vue了,因此最近在学习Vue3.0,Vue的更新机制与React的更新机制是不同的,React的更新机制说的简单点就是根据场景调用不同方法触发状态更新,从而再次进行渲染,而对于Vue的话,我认为是在发生的数据更新时,根据情况进行渲染的。说的专业点就是Vue拥有一个响应式系统,可以让它在数据更新的时候自动进行视图的更新。在Vue3.0中,可以使用reactive声明响应式状态 ,官方例子:

import { reactive } from 'vue'

// 响应式状态
const state = reactive({
  count: 0
})

也可以创建独立的响应式值:

import { reactive } from 'vue'

// 响应式状态
import { ref } from 'vue'

const count = ref(0)

那么本文重点来了,在学习到reactive方法的时候,看到文档说不要解构reactive创建的响应式对象,为什么?,因为会失去响应式的功能,那为什么会失去,因为…(并没有解释),而且在观看一个尤大讲解Vue3的视频中,尤大也说了不要解构reactive创建的响应式对象,为什么?,因为会失去响应式的功能,那为什么会失去,因为…(并没有解释)。这个问题隔了几天直到我调试Vue3.0的reactivity之后,我才有了一丝想法,可以简单的看看在调用reactivity方法之后发生了什么:
①先有个例子:

 <div id="app">
        <p @click="change">
            {{refCount}}
            {{count}}
        </p>
    </div>
		//js代码
        const { reactive, toRefs } = Vue;
        const vm = Vue.createApp({
            setup(props) {
            //创建响应式对象
                const rObj = reactive({
                    count: 0
                });
            //创建点击事件
                const change = () => {
                    console.log(rObj.count)
                    rObj.count++;
                }
            //利用ref保留与源对象的响应式关联
                const { count:refCount } = toRefs(rObj);
                const { count } = rObj;
                return {
                	//具有响应式
                    refCount,
                 	//响应式丢失
                    count,
                    change
                }
            }
        }).mount('#app');

可以看出当点击元素的时候,refCount是随着进行变化的,而count是解构出来的,而它并没有随着变化的。那么调试进入reactive方法:
在这里插入图片描述
可以看到它在内部调用了createReactiveObject方法,这名字很好理解就是创建响应式对象,调试进去:
在这里插入图片描述
它在这里做了一些处理,细节暂时不探究,重点在这:
在这里插入图片描述
创建了一个代理对象将其保存在内部并返回,学习Vue3或多或少都听过Vue3如何进行数据视图更新的,Proxy对数据进行了拦截,当数据发生变化,通知Vue进行视图变化,在new Proxy的第二个参数,它通常使用的baseHanderls:

  const baseHandlers = {
        get(target, key, receiver) {},
        set(target, key, value, receiver) {},
        deleteProxy: (target, key) {},
        has: (target, key) {},
        ownKey: (target) {}
    };

绕了这么久可以看出reactive方法其实就是创建了一个Proxy对象,以及进行了一系列处理,其中并没有找到它可能会失去响应式的情况,也就是说它失去响应式不在于Vue而是在于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);
            }
        });

打印出来的效果:
在这里插入图片描述
这时想一下如何会因为解构而失去响应式(在这里就当作是打印文字),先试试直接赋值会打印啥:

 proxy.count = 2;

在这里插入图片描述

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

		let {count} = proxy;
        count = 2;

这里会打印什么,因为失去响应,所以它只打印出来:
在这里插入图片描述
好像是这样的感觉,那试试对象:

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

直接赋值:

   		proxy.a.count = 2;
        console.log(proxy);

在这里插入图片描述

先只解构一次看看

		let { a } = proxy;
        a.count = 3;
        console.log(proxy);

在这里插入图片描述
解构到底

		let { a } = proxy;
        let { count } = a;
        count = 3;
        console.log(proxy);

在这里插入图片描述
为什么会不同,其实很好理解,只解构一次,其实新的对象的count仍然是被代理的,
在这里插入图片描述

而解构两次,直接获取了count,相当于绕过了代理a。
那么就很好理解了,解构为什么会失去响应,用这个图就可以解释:
在这里插入图片描述
因为解构赋值相当于直接跳过了代理那一层,在下面直接获取值,所以get和set无法被调用。

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值