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

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

时间2025-05-02 21:09:15分类IT科技浏览3382
导读:题引: 在我们从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
网站站点地图生成方法(网站地图生成器,百度谷歌sitemap地图生成) 站群更新软件(站群SEO优化怎么更新文章,站群文章更新系统)