第七节:带你全面理解vue3: 其他响应式进阶API

前言:

针对vue3官网中, 响应式:进阶API 中, 我们在上一章中给大家讲解了shallowRef, shallowReactive, shallowReadonly几个API的使用.

本章主要对剩下的API 进行讲解, 我们先看一下官网中进阶API 都有那些

img

对于剩下这些API, 你需要了解他们创建目的, 是为了解决之前的API存在的那些痛点问题, 这样你就能更好的了解使用他们的细节.工作中就可以有的放矢的选择不同的API.

1. triggerRef

我们首先来分析一下triggerRefAPI 的使用

1.1. triggerRef 针对的痛点问题

我们先看一个痛点问题:

对于ref响应式数据的变化, vue帮我们处理副作用. 比如,页面的更新, watchEffect侦听器回调函数的调用等.

但对于浅层响应数据, 比如shallowRef创建的数据, 其深层并不具有响应性, 也就是说vue并没有监测这些数据的变化, 当对深层数据进行修改时, 并不会触发副作用, 比如页面不会自动刷新.

triggerRefAPI 就是为了解决shallowRef浅层响应式数据深层修改问题.

当深层修改时, 会强制触发依赖于一个浅层 ref 的副作用,这通常在对浅引用的内部值进行深度变更后使用。

1.2. triggerRef 类型

类型:

function triggerRef(ref: ShallowRef): void

triggerRefAPI 函数接收一个shallowRefAPI 创建的数据, 作用就是强制触发这个浅层ref数据的副作用.

1.3. triggerRef 使用示例

示例:

<template><div><h3>shallowReadonly</h3><div>{{ count }}</div><div>{{ count2 }}</div><button @click="change">修改数据源</button></div>
</template><script lang="ts">
import { defineComponent, readonly, ref, shallowReadonly, shallowRef, triggerRef, watchEffect } from 'vue'export default defineComponent({setup() {const count = ref({ num: 0 })const count2 = shallowRef({ num: 0 })// 对于ref 数据, 是深层响应式,// 因此当我们通过count.value.num++ 修改数据时,依然会触发watchEffect副作用函数watchEffect(() => {console.log('count.value.num', count.value.num)})// 因为shallowRef 数据不是深层响应式, 只有.value 整体修改才会触发响应式// 因为当我们通过count2.value.num++ 修改数据时,不会出发watchEffect 副作用函数// 同时视图也不会发生更改watchEffect(() => {console.log('count2.value.num', count2.value.num)})// 修改数据const change = () => {// count.value.num++count2.value.num++// 如果希望shallowRef 深层数据修改后,触发视图更新// 那么就需要使用triggerRef 手动触发更新triggerRef(count2)  // 手动更新count2}return { count, count2, change }}
})
</script>

通过示例的运行结果, 你也可以看出. shallowRef创建响应式数据, 在深层数据发生变化时, 不会触发页面更新 和watchEffect的处理函数. 因为深层不具有响应性.

当我们手动调用triggerRef函数, 并将shallowRef创建数据作为参数, 就是告诉vue , 我们需要强制执行shallowRef数据的副作用. 此时页面将会更新, watchEffect处理函数也会自动执行

1.4. triggerRef 使用小结

在理解triggerRefAPI 的使用后, 针对该API, 我做了以下小结

  • triggerRef常与shallowRef搭配使用
  • triggerRef会强制更新以shallowRef数据作为依赖的副作用,ref数据会自动触发这些副作用

我们需要注意的是: vue3只提供了triggerRef这个方法,但没有提供triggerReactive的方法。 也就是说triggerRef 【不可以】去更改 shallowReactive创建的数据

2. toRaw

根据一个 Vue 创建的代理返回其原始对象

2.1. toRaw 针对的问题

vue3中, 我们通过 reactive()readonly()shallowReactive() shallowReadonly()四个API 创建的响应式数据, 本质上就是通过Proxy创建的代理对象.

但有时我们在做数据传输时, 我们并不需要传响应式数据, 我们只想传最基本的原始对象.

toRawAPI 的作用就是返回 reactive()readonly()shallowReactive(),shallowReadonly() 创建的代理对应的原始对象。

2.2. toRaw 类型

toRaw 函数签名

function toRaw<T>(proxy: T): T

toRawAPI 函数接收一个Proxy代理对象(响应式对象)作为参数,

2.3. toRaw 使用示例

示例:

<template><div><h3>shallowReactive</h3><div>{{ user }}</div><button @click="change">修改数据源</button></div>
</template><script lang="ts">
import { defineComponent, reactive, toRaw } from 'vue'export default defineComponent({setup() {// 代理目标对象const obj = { name: '张三', age: 18 }// reactive 处理的代理对象const user = reactive(obj)// 控制触发代理对象console.log('user', user)// 使用toRaw, 参数是代理对象, 返回代理对象的目标对象console.log('toRaw(user)', toRaw(user))console.log('toRaw(user) === obj', toRaw(user) === obj)  // true// 修改数据const change = () => {user.name = '李四'}return { user, change }}
})
</script>

通过控制台输出结果, 你可以看出, toRaw 就是获取代理对象的原目标对象.

这是一个可以用于临时读取而不引起代理访问/跟踪开销,或是写入而不触发更改的特殊方法。不建议保存对原始对象的持久引用,请谨慎使用。

这句话来自于官网, 这句话你可以这么理解,

代理对象具有响应性, 可以理解为vue在监测这个数据的变化, 这个监测会消耗性能. 如果你的操作不要触发副作用, 就没有必要 使用具有响应性的代理对象.

比如调用接口时传入的参数, 就可以使用toRaw去掉代理对象的外壳, 获取到原始对象传入接口.

3. markRaw

markRaw 函数的作用就是将一个对象转为不可代理对象.

如果使用reactiveAPI , 也不会代理markRaw函数返回的对象, 会直接返回原对象.

示例:

<template><div><h3>shallowReactive</h3><div>{{ user }}</div><button @click="change">修改数据源</button></div>
</template><script lang="ts">
import { defineComponent, markRaw, reactive } from 'vue'export default defineComponent({setup() {// 代理目标对象const obj = { name: '张三', age: 18 }// 将obj原始对象标记为不可代理const markObj = markRaw(obj)// reactive 处理的代理对象const user = reactive(markObj)// user 不是代理对象console.log('user', user)// 修改数据const change = () => {user.name = '李四'}return { user, change }}
})
</script>

控制台输出:

img

通过控制台输出结果, 可以看出, 通过markRaw 处理过的对象具有一个__v_skip的属性, 用于标记这个对象不能创建代理对象, 即响应式数据.

尽管你将该对象传入reactive, 返回的也不是一个代理对象, 而是原对象.

既然不是响应数据,修改user.name 时, 就不会触发视图更新

该API的作用就是, 帮助你给一些你不希望创建为代理对象的原始对象添加标记.

4. effectScope

4.1. effectScope 作用

vue3的使用过程中,我们可能会针对同一个响应式数据创建多个副作用.比如computed, watch, watchEffect等.

再次过程中, 如果关闭某个副作用, 比如watch创建的侦听器, 就需要通过返回值关闭. 那么多个副作用你就需要一个一个关闭. 使用相对麻烦

effectScope字面意思就是副作用作用域, 可以理解为, 该函数创建一个作用域, 将所有的副作用放在共同一个作用域中, 如果以后想统一关闭副作用, 就可以使用作用域整体关闭.

4.2. effectScope

类型

function effectScope(detached?: boolean): EffectScopeinterface EffectScope {run<T>(fn: () => T): T | undefined // 如果作用域不活跃就为 undefinedstop(): void
}

effectScope函数返回一个作用域对象, 即EffectScope类型.

该作用域对象上具有run, stop方法, 同时run方法接收一个回调函数作为参数.

4.3. effectScope 使用方式

通过effectScope函数创建一个 effect 作用域,可以捕获其中所创建的响应式副作用 (即计算属性和侦听器),这样捕获到的副作用可以一起处理。

示例:

<template><div><h3>shallowReactive</h3><div>{{ count }}</div><button @click="change">修改数据源</button></div>
</template><script lang="ts">
import { computed, defineComponent, effectScope, markRaw, reactive, ref, shallowReactive, toRaw, watch, watchEffect } from 'vue'export default defineComponent({setup() {// 创建ref 数据const count = ref(10)// 创建副作用作用域const scope = effectScope()// 控制台输出 effect 作用域console.log("scope", scope);// 收集运行的副作用scope.run(() => {// 计算属性副作用const computedCount = computed(() => count.value * 2)// watch 侦听副作用watch(count,() => {console.log('computedCount', computedCount.value)console.log('watch count', count.value)})// watchEffect 副作用watchEffect(() => {console.log('watchEffect count', count.value)})})console.log('scope', scope) // 2秒以后关闭所有的副作用setTimeout(() => {scope.stop()}, 2000)// 修改数据const change = () => {count.value++}return { count, change }}
})
</script>

控制台输出结果:

img

通过控制台输出的effect作用域对象, 你可以看到, 作用域将回调函数中的副作用进行了收集, 存储在effects属性上.

同时effect作用域对象原型对象上具有run收集副作用的方法, stop关闭副作用的方法.

5. getCurrentScope

getCurrentScope函数返回当前活跃的 effect 作用域。

在前一个API中, 给大家讲解了effectScope函数, 该函数执行后会返回一个effect 作用域, 通过调用effect作用域对象的run方法收集所有副作用. 我们就可以在run方法的回调函数中, 通过getCurrentScope函数获取到正在活跃的effect作用域对象.

示例:

// 创建副作用作用域
const scope = effectScope();
console.log("scope", scope);// 收集运行的副作用
scope.run(() => {// 计算属性副作用const computedCount = computed(() => count.value * 2);// watch 侦听副作用watch(count, () => {console.log("computedCount", computedCount.value);console.log("watch count", count.value);});// watchEffect 副作用watchEffect(() => {console.log("watchEffect count", count.value);});// 通过  getCurrentScope() 获取当前真正活跃的 effect 作用域对象const effectScope = getCurrentScope();console.log("getCurrentScope", effectScope === scope);// 控制台输出结果: getCurrentScope true
});

示例中, 我们通过effectScope创建了一个effect作用域对象, 当调用该作用域对象的run方法,传入回调函数, 会自动执行回调函数, 收集副作用, 并将收集到的副作用保存在副作用effect作用域中. 也就是说, 在执行回调函数时, 我们创建的scope就是活跃的effect作用域

之后,我们通过执行getCurrentScope函数获取当前活跃的副作用作用域, 和之前我们创建的作用域对比, 发现getCurrentScope 获取的就是我们创建的effect作用域.

其实每一个组件都有一个effect作用域, 用于收集组件内所有的副作用. 组件更新函数本身也就是一个副作用. 这也就是响应式数据变化后, 页面会重新渲染的原因.

以及组件被销毁后, vue3 会通过组件的effect作用域清理组件内收集的所有副作用

该API 在工作中并不常使用到. 甚至一个项目里连一次都不会用到.

6. onScopeDispose

该API 函数主要用于调试, 工作中也不怎么常用, 其作用就是在当前活跃的副作用(effect)作用域对象上注册一个调试的回调函数. 在effect作用域关闭时, 会自动调用注册的回调函数,.

示例:

// 创建副作用作用域
const scope = effectScope();
console.log("scope", scope);// 收集运行的副作用
scope.run(() => {// 计算属性副作用const computedCount = computed(() => count.value * 2);// watch 侦听副作用watch(count, () => {console.log("computedCount", computedCount.value);console.log("watch count", count.value);});// watchEffect 副作用watchEffect(() => {console.log("watchEffect count", count.value);});// 在当前活跃的 effect 作用域对象上注册一个回调函数onScopeDispose(() => {console.log("当前effectScope 停止");});
});// 2秒以后关闭所有的副作用
setTimeout(() => {scope.stop();
}, 2000);

示例中, 我们在effectScope收集副作用时, 通过onScopeDispose函数注册了一个回调函数.

effectScope副作用作用域, 即scope对象调用stop方法时, 会自动执行注册的回调函数. 多用于功能调试

7. 结语

至此, 就把vue3中响应式进阶API 中剩余的API函数给大家讲完了, 这里比较常用的API 有triggerRef, toRaw, markRaw, effectScope, 其余两个API 函数并不怎么常用.

这里尤其要注意effectScope, 使用好了可以给代码增色不少.

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

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

相关文章

LLM多模态——GPT-4o改变人机交互的多模式 AI 模型应用

1. 概述 OpenAI 发布了迄今为止最新、最先进的语言模型 – GPT-4o也称为“全“ 模型。这一革命性的人工智能系统代表了一次巨大的飞跃&#xff0c;其能力模糊了人类和人工智能之间的界限。 GPT-4o 的核心在于其原生的多模式特性&#xff0c;使其能够无缝处理和生成文本、音频…

AWPortrait1.4更新,人物的生成更加趋近真实感,将SD1.5人像的真实感提升到了一个新的高度

AWPortrait1.4更新&#xff0c;人物的生成更加趋近真实感&#xff0c;将SD1.5人像的真实感提升到了一个新的高度 经过5个月&#xff0c;AWPortrait终于迎来了1.4。 本次更新基于1.3训练&#xff0c;使得人物的生成更加趋近真实感&#xff0c;将SD1.5人像的真实感提升到了一个新…

uview1.0 u-form表单回显校验不通过

提交到后端的数据&#xff0c;回显后不做任何修改无法通过表单校验 原因&#xff0c;u-form表单校验的类型默认为string&#xff0c;但是后端返回的是integer类型&#xff0c;导致无法通过校验 解决&#xff0c;既然后端返回的是整数形&#xff0c;那么我们就将校验规则的type…

【企业动态】东胜物联成为AWS硬件合作伙伴,助力实现边缘智能

近日&#xff0c;AIoT硬件设备供应商东胜物联与全球领先的云计算服务提供商亚马逊云&#xff08;AWS&#xff09;达成合作关系&#xff0c;共同致力于推动物联网技术的发展&#xff0c;为企业客户提供更智能、灵活的硬件解决方案&#xff0c;助力智能化升级和数字化转型。 作为…

Android studio关闭自动更新

Windows下&#xff1a; 左上角file - setting - Appearance & Behavier - system setting - update - 取消勾选

图书管理系统(Java版本)

文章目录 前言要求1.设置对象1.1.图书1.2.书架2.管理员3.功能的实现 2.搭建框架2.1.登录(login)2.2.菜单2.3.操作方法的获取 3.操作方法的实现3.1.退出系统(ExitOperation)3.2.显示图书(ShowOperation)3.3.查阅图书(FindOperation)3.4.新增图书(AddOperation)3.5.借出图书(Borr…

链游:区块链技术的游戏新纪元

随着区块链技术的快速发展&#xff0c;越来越多的行业开始探索与其结合的可能性&#xff0c;其中&#xff0c;游戏行业与区块链的结合尤为引人注目。链游&#xff0c;即基于区块链技术的游戏&#xff0c;正以其独特的优势&#xff0c;为玩家带来全新的游戏体验。本文将对链游进…

QQ技术导航源码附带交易系统

网站功能 QQ登录 友联自助交换 友情链接交易功能 多功能搜索 ico小图标本地化 网站图片本地化 蜘蛛日志 文章评论 网站评论 自助链接匿名提交站点&#xff0c;添加友链访问网站自动审核通过 VIP 会员等级 VIP 付费升级 单个文章或者站点付费快审 多背景图片可自定义背景图片…

200smart【编程入门】

说明 编程时&#xff0c;遇到困难就按【F1】 【I】输入 200smart 上限 i0.0~i31.7 255bit【255个输入点】 i0.0~i31.7 八进制 【布尔 bool 】 ib0~ib127 【单字节】 8bit iw0~iw127 …

springBoot+springSecurity基本认证流程

springBootspringSecurity认证流程 整合springSecurity 对应springboot版本&#xff0c;直接加依赖&#xff0c;这样版本不会错 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId…

SpringMVC接收请求参数的方式:

接收简单变量的请求参数 直接使用简单变量作为形参进行接收&#xff08;这里简单变量名称需要与接收的参数名称保持一致&#xff0c;否则需要加上RequestParam注解&#xff09;&#xff1a; 细节&#xff1a; 1&#xff1a;SpringMVC会针对常见类型&#xff08;八种基本类型及…

MQTT到串口的转发(node.js)

本文针对以下应用场景&#xff1a;已有通过串口通信的设备或软件&#xff0c;想要实现跨网的远程控制。 node.js安装 从 Node.js — Run JavaScript Everywhere下载LTS版本安装包&#xff0c;运行安装程序。&#xff08;傻瓜安装&#xff0c;按提示点击即可&#xff09; 设置环…

网络传输层

叠甲&#xff1a;以下文章主要是依靠我的实际编码学习中总结出来的经验之谈&#xff0c;求逻辑自洽&#xff0c;不能百分百保证正确&#xff0c;有错误、未定义、不合适的内容请尽情指出&#xff01; 文章目录 1.端口号的基础2.传输层两协议2.1.UDP 协议2.1.1.协议结构2.1.2.封…

CPP Con 2020:Type Traits I

先谈谈Meta Programming 啥是元编程呢&#xff1f;很简单&#xff0c;就是那些将其他程序当作数据来进行处理和传递的编程&#xff08;私人感觉有点类似于函数式&#xff1f;&#xff09;这个其他程序可以是自己也可以是其他程序。元编程可以发生在编译时也可以发生在运行时。…

LAMDA面试准备(2024-05-23)

有没有学习过机器学习&#xff0c;提问了 FP-Growth 相比 Apriori 的优点 1. 更高的效率和更少的计算量&#xff08;时间&#xff09; FP-Growth 通过构建和遍历 FP-树 (Frequent Pattern Tree) 来挖掘频繁项集&#xff0c;而不需要像 Apriori 那样生成和测试大量的候选项集。具…

5.23.2 深度学习提高乳房 X 光检查中乳腺癌的检测率

开发了一种深度学习算法&#xff0c;该算法可以使用“端到端”训练方法在筛查乳房 X 光检查中准确检测出乳腺癌&#xff0c;该方法有效地利用了具有完整临床注释或仅具有整个图像的癌症 标签 的训练数据集。 在这种方法中&#xff0c;仅在初始训练阶段才需要病变注释&#xff…

springboot vue 开源 会员收银系统 (2) 搭建基础框架

前言 完整版演示 前面我们对会员系统https://blog.csdn.net/qq_35238367/article/details/126174288进行了分析 确定了技术选型 和基本的模块 下面我们将从 springboot脚手架开发一套收银系统 使用脚手架的好处 不用编写基础的rabc权限系统将工作量回归业务本身生成代码 便于…

Tensorflow入门实战 P01-实现手写数字识别mnist

目录 1、背景&#xff1a;MNIST手写数字识别 2、完整代码&#xff08;Tensorflow&#xff09;&#xff1a; 3、运行过程及结果&#xff1a; 4、小结&#xff08;还是很清晰的&#xff09; 5、 展望 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客…

Kafka之【生产消息】

消息&#xff08;Record&#xff09; 在kafka中传递的数据我们称之为消息&#xff08;message&#xff09;或记录(record)&#xff0c;所以Kafka发送数据前&#xff0c;需要将待发送的数据封装为指定的数据模型&#xff1a; 相关属性必须在构建数据模型时指定&#xff0c;其中…

JavaEE技术之分布式事务(理论、解决方案、Seata解决分布式事务问题、Seata之原理简介、断点查看数据库表数据变化)

文章目录 JavaEE技术之分布式事务准备:1. 本地事务回顾1.1 什么是事务1.2 事务的作用1.3 事务ACID四大特性1.4 事务的并发问题1.5 MySQL事务隔离级别1.6 事务相关命令(了解)1.7 事务传播行为&#xff08;propagation behavior&#xff09;1.8 伪代码练习1.9 回滚策略1.10 超时事…