详细讲一讲vue3下会造成响应式丢失的情况

 更新时间:2023年06月01日 11:39:12   作者:web老猴子  
vue3开发过程中,绑定的响应式数据失去了响应式,如何解决问题呢,下面这篇文章主要给大家介绍了关于vue3下会造成响应式丢失的情况,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

题引:

在我们从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() 能返回响应式。

最后

到此这篇关于vue3下会造成响应式丢失的情况的文章就介绍到这了,更多相关vue3造成响应式丢失的情况内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • VUE中filters过滤器的两种用法实例

    VUE中filters过滤器的两种用法实例

    vue中过滤器的作用可被用于一些常见的文本格式化,也就是修饰文本,但是文本内容不会改变,下面这篇文章主要给大家介绍了关于VUE中filters过滤器的两种用法,需要的朋友可以参考下
    2022-04-04
  • vue router返回到指定的路由的场景分析

    vue router返回到指定的路由的场景分析

    这篇文章主要介绍了vue router返回到指定的路由的场景分析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • vue项目登录模块滑块拼图验证功能实现代码(纯前端)

    vue项目登录模块滑块拼图验证功能实现代码(纯前端)

    滑块验证作为一种反机器人的工具,也会不断发展和演进,以适应不断变化的威胁,这篇文章主要给大家介绍了vue项目登录模块滑块拼图验证功能实现的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-07-07
  • Vue3中使用ref标签对组件进行操作方法

    Vue3中使用ref标签对组件进行操作方法

    这篇文章主要介绍了Vue3中使用ref标签对组件进行操作方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • 解决vue项目中type=”file“ change事件只执行一次的问题

    解决vue项目中type=”file“ change事件只执行一次的问题

    这篇文章主要介绍了vue项目中解决type=”file“ change事件只执行一次的问题,本文给大家介绍的非常详细,需要的朋友可以参考下
    2018-05-05
  • 浅谈Vue.js组件(二)

    浅谈Vue.js组件(二)

    这篇文章主要介绍了Vue.js组件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • element-ui图片上传组件查看和限制方式

    element-ui图片上传组件查看和限制方式

    这篇文章主要介绍了关于element-ui图片上传组件查看和限制方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Vite中使用Ant Design Vue3.x框架教程示例

    Vite中使用Ant Design Vue3.x框架教程示例

    这篇文章主要为大家介绍了Vite中使用Ant Design Vue3.x框架教程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • 浅谈vue.js导入css库(elementUi)的方法

    浅谈vue.js导入css库(elementUi)的方法

    下面小编就为大家分享一篇浅谈vue.js导入css库(elementUi)的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • vue实现element表格里表头信息提示功能(推荐)

    vue实现element表格里表头信息提示功能(推荐)

    小编最近接了这样一个需求,需要在element表格操作一栏添加提示功能,下面小编给大家带来了基于vue实现element表格里表头信息提示功能,需要的朋友参考下吧
    2019-11-11

最新评论