首页IT科技vue响应式ui(讲讲vue3下会造成响应式丢失的情况)

vue响应式ui(讲讲vue3下会造成响应式丢失的情况)

时间2025-09-19 08:18:53分类IT科技浏览5333
导读:题引: 在我们从vue2过渡到vue3的时候,对于数据响应式的变化其实是懵懵懂懂的。从以往直接在data函数里面定义变量到每一次都要使用ref/reactive时,是有些不适应的。但问题不大,毕竟在大前端时代中,如果不及时跟上时代的步伐,不仅技术没跟上,面试还容易被卡。所以今天来聊聊在使用...

题引:

在我们从vue2过渡到vue3的时候                ,对于数据响应式的变化其实是懵懵懂懂的                。从以往直接在data函数里面定义变量到每一次都要使用ref/reactive时                         ,是有些不适应的                         。但问题不大        ,毕竟在大前端时代中            ,如果不及时跟上时代的步伐                         ,不仅技术没跟上             ,面试还容易被卡        。所以今天来聊聊在使用vue3开发时对于数据响应式的理解            。

vue3的响应式是基于 proxy

从vue2的 Object.defineProperty 到vue3的 proxy 可谓是一个质的飞跃                         。vue2的响应式是需要递归+遍历每一个对象的属性进行数据劫持        ,而在vue3中只需要对对象层进行监听即可             。好了话不多说                        ,开始讲解一些常见的响应式问题        。

ref和reactive之间的关系

如果我们用ref定义基本类型时                 ,实际上还是使用 Object.defineProperty 进行数据劫持监听                        。但如果是定义引用类型时    ,底层代码上是借用 reactive 函数进行数据劫持的                 。因此ref和reactive关系是紧凑的    。通过源码的我们是可以确认的                        。

我们可以看到                        ,this_value = useDirectValue ? newVal : toReactive(newVal) 是进行了判断                     ,而 useDirectValue 是进行判断是否是浅层的                、仅可读的数据                     。 那么如果我们传入的是一个对象,那么就会进入 toReactive(newVal) 这一步。 toReactive 函数就是进行reactive定义的函数入口                    。

reactive定义的变量重新赋值会失去响应式                    ,而ref不会

我们一开始接触vue3的时候                         ,会对这个问题十分的不解    ,只是知道有这个问题而不知其根                ,今天就来讲讲这个问题                         。

import {ref,reactive} from vue; let test = {age:2}; let obj = reactive({age:1}) let obj1 = ref({age:1}) obj = test; obj1.value = test;

通过reactive()包含的对象是进行了内部的proxy代理                         ,因此具有响应式    。但是像test这个对象        ,它是没有进行数据劫持的            ,而对象赋值的时候实际上是引用地址赋值                。那么obj这个对象变成了一个没有数据劫持的引用地址                         ,那么它也就失去了响应式                         。但是obj1重新赋值时会保留自身的响应式        。其实很简单             ,跟上图的代码是有关的            。细心的人会发现        ,在 set 函数里面有这么一段代码                         。

是的                        ,在我们对ref定义的变量重新赋值时会进入 set 函数                 ,且重新赋值的是一个对象的话    ,那么它会再次进入 toReactive 函数进行数据劫持                        ,这就是为什么ref定义的变量重新赋值对象时依旧保留响应式的根本原因             。

解构响应式对象会造成响应式丢失

通过上面我都知道                     ,不管是ref还是reactive定义的对象变量,都会经过 reactive 函数来进行proxy代理        。但是即使是对象                    ,也会出现响应式丢失的情况                        。

<script setup> import {reactive,onMounted} from vue; let obj = {a:18,aa:{age:18},aaa:{friend:{age:18}} } let rect = reactive(obj); let {a,aa,aaa} = rect; onMounted(()=>{setTimeout(()=>{a = 2;aa.age = 2;aaa.friend.age = 2;},2000) }) </script> <template><div>{{a}}</div><div>{{aa.age}}</div><div>{{aaa.friend.age}}</div> </template>

上面的运行结果就是                         ,a变量没有响应式    ,aa和aaa都是响应式                 。这是因为在解构赋值中                ,如果是原始类型的话是按照值传递                         ,如果是引用类型的话是按照引用地址传递    。除此之外 reactive() 定义的变量中 get函数 有这样的一个处理

a = rect.a; //rect.a是一个基本类型        ,所以是直接赋值 aa = rect.aa; //rect.aa是一个引用类型            ,在内部处理时触发条件判断                         ,且非可读对象即从Map数据结构中返回已经代理的响应式对象 aaa = rect.aaa //跟rect.aa一个道理

因此以后对响应式对象进行解构时             ,记住以上的内部判断逻辑就可以拿捏它们了(#.#)                        。当然        ,对vuex或者pinia的取值也是这个道理                        ,也就是为什么需要借助 computed() 来实现响应式了                     。因此 computed() 能返回响应式。

最后

整理了75个JS高频面试题                 ,并给出了答案和解析    ,基本上可以保证你能应付面试官关于JS的提问                    。

有需要的小伙伴                        ,可以点击下方卡片领取                     ,无偿分享

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
微信有没有机器人聊天的小程序(基于小程序制作一个ChatGPT聊天机器人)