第六节:带你全面理解vue3 浅层响应式API: shallowRef, shallowReactive, shallowReadonly

前言

前面两章,给大家讲解了vue3ref, reactive,readonly创建响应式数据的API, 以及常用的计算属性computed, 侦听器watch,watchEffect的使用

其中reactive, ref, readonly创建的响应式数据都是深层响应.

而本章主要给大家讲解以上三个API 对应的创建浅层响应式数据的 API, 即shallowRef, shallowReactive, shallowReadonly

1. shallowRef

shallowRefref 浅层作用形式。其实就是浅层响应式

shalloRef的使用方式和ref()完全相同, 不同的只是vue对数据响应式处理的不同:

  • ref创建的数据, 如果有深层, 比如参数是一个对象, 对象的属性就是深层, 参数对象会被vue通过reactive处理为深层响应
  • shallowRef创建数据, 只有顶层的value属性具有响应性, 深层的数据不具有响应性, 会原因返回, 即vue不会递归的将深层数据通过reactive处理, 而是原样存储和暴露.

1.1. 类型

我们先看一下shallowRefAPI 的类型签名, 其签名如下:

function shallowRef<T>(value: T): ShallowRef<T>interface ShallowRef<T> {value: T
}

通过签名可以简单的看出, shallowRefAPI 接收一个参数, 返回一个具有value属性的对象, 且value属性的类型和参数类型相同.

1.2. ref 和shallowRef 处理原始数据类型

接下会通过示例带大家看一下refshallowRef 在处理原始数据类型的有什么不同.

示例代码:

<template><div><h3>shallowRef</h3><div>{{ count }}</div><div>{{ count2 }}</div><button @click="change">修改数据源</button></div>
</template><script lang="ts">
import { defineComponent, ref, shallowRef } from 'vue'export default defineComponent({setup() {const count = ref(0)const count2 = shallowRef(0)// 控制台输出 ref, shallowRef 创建的数据consollog("count", count);console.log("count2", count2);// 修改数据const change = () => {// count.value++count2.value++}return { count, count2, change }}
})
</script>

控制台输出结果

img

通过代码的运行结果, 你可以看出,

在参数为基本数据类型的情况下, refshallowRef创建的响应式数据在使用上完全一样, value属性都具有响应性

通过控制台输出结果, 你会发现refshallowRef创建的ref对象极度相似,
如果你阅读过源码, 你就会明白, ref, shallowRef返回对象是通过同一个类实例化的对象.因此两个实例对象具有相同的属性. 但是有一个属性__v_isShallow属性值不同, 因为vue通过这个属性来区分是ref还是shallowRef创建的对象.

这里不对源码实现做过多阐述, 如果你对源码感兴趣, 可以关注我的vue3源码专栏


1.3. ref 和shallowRef 处理深层对象

refshallowRef 在处理深层对象就会有所不同:

  • ref函数在处理深层对象时, 深层对象会被vue自动调用reactive包裹成响应式数据,
  • shallowRef函数在处理深层对象时, vue不同将深层对象包裹为响应式对象, 也就是说shallowRef只有.value属性值才具有响应性, 深层对象不具有响应性

示例:

<template><div><h3>shallowRef</h3><div>{{ count }}</div><div>{{ count2 }}</div><button @click="change">修改数据源</button></div>
</template><script lang="ts">
import { defineComponent, ref, shallowRef } from 'vue'export default defineComponent({setup() {const count = ref({ count: 0 })const count2 = shallowRef({ count: 0 })// 控制输出 ref, shallowRef 对于参数为对象时创建的ref 对象console.log('count', count)console.log('count2', count2)// 修改数据const change = () => {// count.value.count++// 不会触发响应式// count2.value.count++// count2 是shallowRef数据// shallowRef 数据只有通过.value 整体修改时才会触发响应式count2.value = { count: 3 }}return { count, count2, change }}
})
</script>

控制台输出:

img

通过控制台输出ref, shallowRef 创建的响应数据, 以及示例的运行结果, 会发现:

  • shallowRef在参数为深层对象时, 创建的ref数据, value值就是参数原对象, 不具有响应性
  • refvalue属性值, 是vue调用reactive函数包裹成的Proxy代理对象, 即响应式数据

因此, 你可以理解shallowRefref 浅层响应式的API, 只有通过.value修改数据才会触发响应式, 深层对象没有通过reactive包裹, 因此深层操作数据不具有响应式

shallowRef() 常常用于对大型数据结构的性能优化或是与外部的状态管理系统集成。


2. shallowReactive

shallowRefref关系相似,

shallowReactivereactive浅层作用形式。就是创建具有浅层响应性的数据


2.1. shallowReactive 类型

首先,我们先看一下shallowReactive类型签名, 签名如下:

function shallowReactive<T extends object>(target: T): T

通过签名可以看出, shallowReactive函数接收一个对象作为参数, 返回类型与参数类型相同

2.2. shallowReactive 浅层响应式

reactive() 不同,shallowReactive创建响应对象没有深层级的转换:一个浅层响应式对象里只有根级别的属性是响应式的, 深层对象不会被vue自动包装为响应对象.

示例:

<template><div><h3>shallowReactive</h3><div>{{ user }}</div><div>{{ user2 }}</div><button @click="change">修改数据源</button></div>
</template><script lang="ts">
import { defineComponent, reactive, shallowReactive } from 'vue'export default defineComponent({setup() {const user = reactive({ name: '张三', age: 18, friend: { name: '李四' } })const user2 = shallowReactive({ name: '张三', age: 18, friend: { name: '李四' } })// 控制台输出reactive, shallowReactive 创建的深层对象console.log("reactive friend", user.friend);console.log("shallowReactive friend", user2.friend);// 修改数据const change = () => {// 1. reactive, shallowReactive 在处理第一层对象属性时// 都会触发响应式// user.name = "王五"  // 修改 reactive// user2.name = "王五"  // 修改 shallowReactive// 2. 操作深度属性,shallowReactive 不会触发响应性// user.friend.name = '王五'  // 修改 reactiveuser2.friend.name = '王五'  // 修改 shallowReactive  不触发响应式}return { user, user2, change }}
})
</script>

控制台输出结果:

img

通过控制台输出结果, 你应该已经看出:

  • reactive创建的响应数据(代理对象) 深层对象也会自动的调用reactive函数, 创建为响应数据
  • shallowReactive创建浅层响应数据, 其深层对象就是原样的不同对象, 不具有响应性.

运行结果也可以看出, 修改shallowReactive深层对象的数据, 页面是不会有任何变化的.因为不具有响应性.

2.3. shallowReactive 深层ref 数据不会自动解包

shallowReactive()函数创建一个浅层响应式对象里只有根级别的属性是响应式的。

也可以说shallowReactive()函数创建的数据是非深度监听, 只会包装第一个对象, 这也就意味着深层的ref数据不会被自动解包.

因为shallowReactive 深层数据的存储是原样存储, 不会包裹为深度响应式,

示例:

<template><div><h3>shallowReactive</h3><div>{{ user }}</div><div>{{ user2 }}</div><button @click="change">修改数据源</button></div>
</template><script lang="ts">
import { defineComponent, reactive, ref, shallowReactive } from 'vue'export default defineComponent({setup() {const count = ref(10)const user = reactive({ name: '张三', age: 18, count })const count2 = ref(20)const user2 = shallowReactive({ name: '张三', age: 18, count: count2 })// 修改数据const change = () => {// 1. reactive 操作深层ref 数据时,自动解包// 此时修改user.count 数据时不用添加.value// user.count = 20  // 修改 reactive// 2. shallowReactive 操作深层ref 数据时,不会自动解包// 此时修改user2.count 数据时必须使用.valueuser2.count.value = 40  // 修改 shallowReactive}return { user, user2, change }}
})
</script>

2.4. shallowReactive与shallowRef 使用比较

  1. 一般情况下使用refreactive即可
  2. 如果有一个对象数据, 结构比较深, 但只有一层对象的属性变化会触发响应, 使用shallowReactive
  3. 如果有一个对象数据, 后面会产生新的对象来整体替换触发响应式, 使用shallowRef

3. shallowReadonly

shallowReadonlyreadonly浅层作用形式。只有第一层是只读的,深层不是只读属性,

也可以这么理解, 只有第一层的对象属性不能修改值, 但深层的数据是可以修改的, 是非深层只读

3.1. shallowReadonly 浅层只读

shallowReadonly在使用上与readonly完全相同, 区域在于:

  • readonly() 创建只读代理, 如果有深层对象, 深层对象也会自动调用readonly处理为只读代理
  • shallowReadonly 创建的是浅层只读代理, 也就是深层对象不会自动调用readonly包裹, 所以深层对象是非只读的, 即可以修改的. 也就意味着只有根层级的属性变为了只读。

示例:

<template><div><h3>shallowReadonly</h3><div>{{ user }}</div><div>{{ user2 }}</div><button @click="change">修改数据源</button></div>
</template><script lang="ts">
import { defineComponent, readonly, ref, shallowReadonly } from 'vue'export default defineComponent({setup() {const user = readonly({ name: '张三', age: 18, friend: { name: '李四' } })const user2 = shallowReadonly({ name: '张三', age: 18, friend: { name: '李四' } })// 修改数据const change = () => {// readonly 为深层只读, 修改任何一层属性值都是不合法// user.name = '王五'// user.friend.name = '王五'// shallowReadonly 只有第一层会被转为只读, 深层属性会原样存储,不是只读的// user2.name = '王五'  // shallowReadonly 第一层修改报错,因为是只读的// shallowReadonly 修改生成不会报错,// 但也不会触发响应性, 因为原样存储就是一个普通对象user2.friend.name = '王五'}return { user, user2, change }}
})
</script>

3.2. shallowReadonly 处理深层ref不会自动解包

因为shallowReadonly 深层数据的存储是原样存储, 不会自动调用shallowReadonly转为只读, 因此对于深层的ref 的数据不会被自动解包了。

示例:

<template><div><h3>shallowReadonly</h3><div>{{ user }}</div><div>{{ user2 }}</div></div>
</template><script lang="ts">
import { defineComponent, readonly, ref, shallowReadonly } from 'vue'export default defineComponent({setup() {const count = ref(10)const user = readonly({ name: '张三', age: 18, count })const count2 = ref(20)const user2 = shallowReadonly({ name: '张三', age: 18, count: count2 })// readonly 处理深层数据为ref 数据时, 会自动解包,不用添加.valueconsole.log('user.count', user.count)// shallowReadonly 获取深层ref 数据时必须添加.value, 因为不会自动解包console.log('user2.count', user2.count.value)return { user, user2 }}
})
</script>

4. 结语

至此, 就把shallowRef, shallowReactive,shallowReadonly给大家讲解完了, 这三个API使用上还是相对较少. 大家要理解这些API的使用原理, 工作中根据情况选择不同的API .

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/15956.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【STM32单片机】----实现LED灯闪烁实战

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

【机器学习-23】关联规则(Apriori)算法:介绍、应用与实现

在现代数据分析中&#xff0c;经常需要从大规模数据集中挖掘有用的信息。关联规则挖掘是一种强大的技术&#xff0c;可以揭示数据中的隐藏关系和规律。本文将介绍如何使用Python进行关联规则挖掘&#xff0c;以帮助您发现数据中的有趣模式。 一、引言 1. 简要介绍关联规则学习…

动态路由实验—OSPF

动态路由协议实验-------OSPF 链路状态路由选择协议又被称为最短路径优先协议&#xff0c;它基SPF&#xff08;shortest path first &#xff09;算法 实验要求&#xff1a;各个PC之间能够互通 1.四台PC配置如下 PC1 PC2 PC3 PC4 2.配置各个交换机的口子的IP R1 <HUAWE…

spiderfoot一键扫描IP信息(KALI工具系列九)

目录 1、KALI LINUX简介 2、spiderfoot工具简介 3、在KALI中使用spiderfoot 3.1 目标主机IP&#xff08;win&#xff09; 3.2 KALI的IP 4、命令示例 4.1 web访问 4.2 扫描并进行DNS解析 4.3 全面扫描 5、总结 1、KALI LINUX简介 Kali Linux 是一个功能强大、多才多…

基于docxtpl的模板生成Word

docxtpl是一个用于生成Microsoft Word文档的模板引擎库。它结合了docx模块和Jinja2模板引擎&#xff0c;使用户能够使用Microsoft Word模板文件并在其中填充动态数据。这个库提供了一种方便的方式来生成个性化的Word文档&#xff0c;并支持条件语句、循环语句和变量等控制结构&…

如何在 Elasticsearch 中选择精确 kNN 搜索和近似 kNN 搜索

作者&#xff1a;来自 Elastic Carlos Delgado kNN 是什么&#xff1f; 语义搜索&#xff08;semantic search&#xff09;是相关性排名的强大工具。 它使你不仅可以使用关键字&#xff0c;还可以考虑文档和查询的实际含义。 语义搜索基于向量搜索&#xff08;vector search&…

大数据工具之HIVE-参数调优,调度乱码(二)

一、调度乱码 在利用HUE工具,搭建WORKFLOW流程的过程中,如果直接执行hivesql数据正常,不会出现乱码现象,如果利用WORKFLOW搭建的流程,进行数据的拉取,会出现数据中文乱码现象,这些乱码主要是由于select 中的硬编码中文导致出现的现象 具体现象如下: select case when …

TG5032CGN TCXO 超高稳定10pin端子型适用于汽车动力转向控制器

TG5032CGN TCXO / VC-TCXO是一款应用广泛的晶振&#xff0c;具有超高稳定性&#xff0c;CMOS输出和使用晶体基振的削波正弦波输出形式。且有低相位噪声优势&#xff0c;是温补晶体振荡器(TCXO)和压控晶体振荡器(VCXO)结合的产物&#xff0c;具有TCXO和VCXO的共同优点&#xff0…

微信小程序上线必备:SSL证书申请以及安装

一、认识ssl证书 1、ssl证书是什么&#xff1f; SSL证书&#xff0c;全称Secure Socket Layer Certificate&#xff0c;是一种数字证书&#xff0c;它遵循SSL&#xff08;现在通常指TLS&#xff0c;Transport Layer Security&#xff09;协议标准&#xff0c;用于在客户端&…

SpringCloud系列(26)--OpenFeign超时控制

前言&#xff1a;在上一章节中我们简单的介绍了如何使用OprnFeign去调用微服务&#xff0c;因为消费侧和服务侧是两个不同的微服务&#xff0c;这样可能会出现超时的现象&#xff0c;例如服务侧需要3秒处理任何才能返回结果&#xff0c;但消费侧可能2秒就断开连接了&#xff0c…

【深度学习】2.单层感知机

目标&#xff1a; 实现一个简单的二分类模型的训练过程&#xff0c;通过模拟数据集进行训练和优化&#xff0c;训练目标是使模型能够根据输入特征正确分类数据。 演示: 1.通过PyTorch生成了一个模拟的二分类数据集&#xff0c;包括特征矩阵data_x和对应的标签数据data_y。标签…

加密与安全_AES RSA 密钥对生成及PEM格式的代码实现

文章目录 RSA&#xff08;非对称&#xff09;和AES&#xff08;对称&#xff09;加密算法一、RSA&#xff08;Rivest-Shamir-Adleman&#xff09;二、AES&#xff08;Advanced Encryption Standard&#xff09; RSA加密三种填充模式一、RSA填充模式二、常见的RSA填充模式组合三…

新业务 新市场 | 灵途科技新品亮相马来西亚亚洲防务展

5月6日&#xff0c;灵途科技携新品模组与武汉长盈通光电&#xff08;股票代码&#xff1a;688143&#xff09;携手参加第18届马来西亚亚洲防务展。首次亮相海外&#xff0c;灵途科技便收获全球客户的广泛关注&#xff0c;为公司海外市场开拓打下坚实基础。 灵途科技与长盈通共同…

Dbs封装_连接池

1.Dbs封装 每一个数据库都对应着一个dao 每个dao势必存在公共部分 我们需要将公共部分抽取出来 封装成一个工具类 保留个性化代码即可 我们的工具类一般命名为xxxs 比如Strings 就是字符串相关的工具类 而工具类 我们将其放置于util包中我们以是否有<T>区分泛型方法和非泛…

Python并发编程学习记录

1、初识并发编程 1.1、串行&#xff0c;并行&#xff0c;并发 串行(serial)&#xff1a;一个cpu上按顺序完成多个任务&#xff1b; 并行(parallelism)&#xff1a;任务数小于或等于cup核数&#xff0c;多个任务是同时执行的&#xff1b; 并发(concurrency)&#xff1a;一个…

计算机SCI期刊,IF=8+,专业性强,潜力新刊!

一、期刊名称 Journal of Big data 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;计算机科学 影响因子&#xff1a;8.1 中科院分区&#xff1a;2区 出版方式&#xff1a;开放出版 版面费&#xff1a;$1990 三、期刊征稿范围 《大数据杂志》发表了关于…

2024年【T电梯修理】考试内容及T电梯修理新版试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【T电梯修理】考试内容及T电梯修理新版试题&#xff0c;包含T电梯修理考试内容答案和解析及T电梯修理新版试题练习。安全生产模拟考试一点通结合国家T电梯修理考试最新大纲及T电梯修理考试真题汇总&#xff0c;…

(2024,SDE,对抗薛定谔桥匹配,离散时间迭代马尔可夫拟合,去噪扩散 GAN)

Adversarial Schrdinger Bridge Matching 公众号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 简介 4. 实验 0. 摘要 薛定谔桥&#xff08;Schrdinger Bridge&#xff0c;SB&…

浮点型比较大小

浮点数的存储形式 浮点数按照在内存中所占字节数和数值范围&#xff0c;可以分为浮点型&#xff0c;双精度浮点型和长双浮点型数。 代码&#xff1a; printf("lgn:%e \n", pow(exp(1), 100));printf("lgn:%f ", pow(exp(1), 100));输出结果&#xff1a; …

CLIP 论文的关键内容

CLIP 论文整体架构 该论文总共有 48 页&#xff0c;除去最后的补充材料十页去掉&#xff0c;正文也还有三十多页&#xff0c;其中大部分篇幅都留给了实验和响应的一些分析。 从头开始的话&#xff0c;第一页就是摘要&#xff0c;接下来一页多是引言&#xff0c;接下来的两页就…