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

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

时间2025-08-05 05:59:51分类IT科技浏览4683
导读:题引: 在我们从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
aieg(全面带你了解AIGC的风口)