Vue 3 watchEffect:如何用 onInvalidate 优化副作用处理

在 Vue3 中,watchEffect 是一个用于在响应式数据变化时自动重新执行的函数。它在创建响应式副作用时特别有用,比如在某些数据变化时更新 DOM、发起网络请求或处理复杂的逻辑。

watchEffect 的 onInvalidate 是一个非常重要的功能,用于处理副作用函数,理解它可以帮助我们在复杂的应用中更好地管理资源,避免内存泄漏和不必要的副作用执行。

1. watchEffect 基本使用

watchEffect 用于自动追踪其内部副作用函数中的响应式数据,当这些数据发生变化时,副作用函数会重新执行。

举个 🌰

import { ref, watchEffect } from 'vue';
const count = ref(0);
watchEffect(() => {console.log(`Count is: ${count.value}`);
});

2. onInvalidate 基本使用

onInvalidate 是一个参数,用于处理副作用的取消或清理操作。当在副作用函数中使用了某些资源(如定时器、订阅等),可能需要在副作用函数重新执行之前清理这些资源,以防止内存泄漏或其他问题。

举个 🌰

<template><div><p>当前计数: {{ count }}</p><button @click="count++">增加计数</button></div>
</template>
<script>
import { ref, watchEffect } from 'vue';
export default {setup() {const count = ref(0);watchEffect((onInvalidate) => {console.log('副作用函数执行');const timer = setInterval(() => {console.log(`计时器中 count 的值: ${count.value}`);}, 1000);onInvalidate(() => {console.log('清除计时器');clearInterval(timer);});});return {count,};},
};
</script>

按道理而言:使用 onInvalidate 清理计时器,每次 count 变化时,watchEffect 会重新执行,在此之前 onInvalidate 会先清理掉之前的计时器,避免重复创建计时器导致内存泄漏。

当我们点击按钮改变 count 值时,watchEffect 重新执行,每秒打印出值,但是 onInvalidate 失效,console.log 没有输出“清楚计时器”,大家可以先分析一下为什么哦?

原因:

watchEffect 的 onInvalidate 在依赖项发生变化时会被触发,关键在于依赖的正确追踪。而上面代码中,count 的变化没有触发 onInvalidate,是因为 watchEffect 没有正确追踪到 count 的依赖。

watchEffect 只能追踪在副作用函数内部使用的响应式数据。如果在 watchEffect 没有直接使用 count.value ,那么它的变化就不会触发副作用函数重新执行,从而不会调用 onInvalidate 清理之前的计时器。

虽然在 setInterval 的回调函数中使用了 count.value,但这并不足以让 watchEffect 追踪到 count 的变化。watchEffect 只会在它同步执行的那一刻,追踪它直接访问的响应式数据。如果响应式数据只是在异步回调(如 setInterval)中访问,它将不会触发 watchEffect 的重新执行。

解决方案:

在 watchEffect 的主逻辑中,直接访问 count.value 即可。

<template><div><p>当前计数: {{ count }}</p><button @click="count++">增加计数</button></div>
</template>
<script>
import { ref, watchEffect } from 'vue';
export default {setup() {const count = ref(0);watchEffect((onInvalidate) => {// 在函数内直接读取 count.value,确保它被追踪,这一步很重要!!!console.log(`副作用函数执行,count 值为: ${count.value}`);const timer = setInterval(() => {console.log(`计时器中 count 的值: ${count.value}`);}, 1000);onInvalidate(() => {console.log('清除计时器 timer');clearInterval(timer);});});return {count,};},
};
</script>

此时控制台输出的结果就是我们预期的!

3. 引入原因

1、清理副作用

在副作用函数中使用 onInvalidate 可以确保在副作用函数重新执行之前,之前的副作用会被正确清理。这样可以避免资源泄漏,例如未清除的定时器或未取消的事件监听器。

2、处理异步操作

对于异步操作(如 API 请求),onInvalidate 可以用于取消未完成的请求。例如,在某个数据变化时,取消之前发出的请求。

3、避免性能问题

在副作用函数中进行清理操作可以避免重复的资源消耗,提升应用性能。例如,在组件卸载时清理定时器或订阅可以避免不必要的计算和内存使用。

4. 注意事项

1、副作用函数的重用

onInvalidate 只在副作用函数重新执行之前调用。如果副作用函数的逻辑是复用的,确保清理操作不会在副作用函数的每次执行中重复触发。

2、异步操作的取消

对于异步操作,确保在 onInvalidate 中正确地取消操作。如果使用 fetch 或其他异步 API,考虑使用 AbortController 进行取消。

3、不必要的清理

避免在 onInvalidate 中做过多的清理操作,确保只处理真正需要的清理逻辑。

举个 🌰

假设有一个网络请求场景,每当数据变化时都会重新发起网络请求,但如果请求未完成时数据再次变化,则会取消之前的请求。在这里,我们只希望 onInvalidate 在新的请求发起之前调用,而不是每次请求逻辑执行时都重复触发清理操作。

<template><div><p>当前ID: {{ id }}</p><button @click="id++">增加 ID</button><p>结果: {{ result }}</p></div>
</template><script>
import { ref, watchEffect } from 'vue';
export default {setup() {const id = ref(1);const result = ref('');watchEffect((onInvalidate) => {console.log(`发起新的请求,ID 为: ${id.value}`);// 模拟一个网络请求const controller = new AbortController();fetch(`https://xxx.xxx.com/posts/${id.value}`, { signal: controller.signal }).then((response) => response.json()).then((data) => {console.log('请求成功:', data);result.value = data.title;}).catch((error) => {if (error.name === 'AbortError') {console.log('请求被取消');} else {console.error('请求失败:', error);}});// 只在发起新请求之前,取消前一次的请求onInvalidate(() => {console.log('清理函数执行,取消之前的请求');controller.abort();});});return {id,result,};},
};
</script>

初次加载时:

正常点击展示:

当按钮点击过快时:

总结

onInvalidate 是 watchEffect 中用于清理副作用函数的有力工具。它可以帮助开发者在副作用函数重新执行之前清理掉不需要的资源或取消正在进行的操作,从而提高应用的性能和稳定性。

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

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

相关文章

blender我的对称模型好像中点被我不小心移动了 我现在如果雕刻 两边修改的地方不是对称的 我该怎么办

blender我的对称模型好像中点被我不小心移动了 我现在如果雕刻 两边修改的地方不是对称的 我该怎么办 首先请调整好模型确保左右前后对其相应的xyz轴 之后CtrlA应用变换 确保这些都归0且模型和xyz轴对应 如果在Blender中模型的中点&#xff08;对称轴&#xff09;不小心被移动了…

使用豆包MarsCode 编写 Node.js 全栈应用开发实践

以下是「豆包MarsCode 体验官」优秀文章&#xff0c;作者狼叔。 欢迎更多用户使用豆包MarsCode 并分享您的产品使用心得及反馈、创意项目开发等&#xff0c;【有奖征集&#xff5c;人人都是豆包MarsCode 测评官&#xff01;】活动正在火热进行中&#xff0c;欢迎大家投稿参加&a…

6-Python基础编程之数据类型操作——数值、布尔和字符串

Python基础编程之数据类型操作——数值、布尔和字符串 数值整数浮点数复数常用操作 布尔类型字符串字符串拼接字符串切片常用函数查找计算转换操作填充压缩分割拼接判定操作 数值 表现形式&#xff1a;整数&#xff08;int&#xff09;、浮点数&#xff08;float&#xff09;、…

校园管理|基于springboot+vue的校园管理系统(源码+数据库+文档)

校园管理|校园管理系统 目录 基于springbootvue的校园管理系统 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师&#xff0c…

自动化表格处理的革命:智能文档系统技术解析

在当今数据驱动的商业环境中&#xff0c;表格数据的自动化处理成为了企业提高效率、降低成本的关键。企业智能文档系统在智能表格识别方面展现出卓越的性能&#xff0c;通过精准识别和处理各种通用表格&#xff0c;显著提升了企业文档管理的智能化水平。本文将深入探讨该系统在…

[产品管理-6]:NPDP新产品开发 - 4 - 战略 - 创新支持战略,支持组织的总体创新战略(平台战略、技术战略、营销战略、知识产权战略、能力建设战略)

目录 一、创新支持战略概述 二、平台战略&#xff1a;大平台小产品战略 2.1 概述 1、平台战略的定义 2、平台战略的特点 3、平台战略的应用领域 4、平台战略的成功案例 5、平台战略的发展趋势 2.2 大平台小产品战略 1&#xff09;大平台的建设 2&#xff09;、小产品…

王牌功能 | 法大大“用户角色权限管理”,合同数据分流、管理权限分层都搞定!

合同签了还得管&#xff0c; 按业务、按项目、按岗位级别… 关于法大大“用户角色权限管理”功能的使用&#xff1a;企业操作人员在电子合同平台创建企业后&#xff0c;需添加企业组织架构&#xff0c;主要添加合同操作相关的人员&#xff0c;即可实现合同操作与数据权限的管理…

QT 对话框 仿文本编辑器

对话框通常是一个顶层窗口&#xff0c;出现在程序最上层&#xff0c;用于实现短期任务或者简洁的用户交互 一、消息对话框&#xff08;QMessageBox&#xff09; 1、QMessageBox类成员函数实现 1&#xff09;实例化 QMessageBox类 对象 2&#xff09;设置对象属性 3&#x…

用API接口可以实现哪些功能(天猫API接口|京东API接口)

在电商领域&#xff0c;API接口可以实现多种功能&#xff0c;起到连接内外部系统及优化电商业务流程等多种作用&#xff0c;从而来提高电商企业的运营效率。 具体来看&#xff0c;API接口可以用来&#xff1a; 商品管理&#xff1a; API接口能够用来获取商品详情等&#xff0…

顶级PCVR头显具备什么配置?清晰度如何?

头戴式显示器是VR体验中用户与虚拟现实环境交互不可或缺的一部分。高端的头显通常可为使用者提供具有超高分辨率的高清画面&#xff0c;因此当你拥有一部高端的VR头显&#xff0c;虚拟世界将如真实世界一样呈现在你眼前。 说到顶级头显我们就不得不提到Varjo&#xff0c;Varjo是…

DBeaver连接数据库报连接错误:Public Key Retrieval is not allowed

问题描述 使用DBeaver软件连接mysql数据库的时候&#xff0c;有如下提示信息&#xff1a; 解决办法 点击驱动属性->找到allowPublicKeyRetrieval这项&#xff0c;把值设置为TRUE,再点击连接测试 可以成功连接到mysql数据库&#xff0c;问题解决~

杰发科技Bootloader(3)—— 基于7801的APP切到Boot

为了方便在APP中跳转到Boot重新进行升级&#xff0c;有两种办法&#xff0c;7840同样可以使用。 1. 调用reset接口进行复位&#xff0c;复位后会先进Boot&#xff0c;再自动跳转到App。 NVIC_SystemReset(); 2. 直接使用跳转指令&#xff0c;参考Boot跳转到App代码&#xff0…

一种简易CAN数据分析器的实现(一)【工程创建+CAN波特率计算工具】

程序实现详见《一种简易CAN数据分析器的实现&#xff08;二&#xff09;【程序实现】》 微信公众号关注&#xff1a;掌芯元器&#xff0c;免费为大家提供嵌入式相关的技术咨询&#xff01;&#xff01;&#xff01; 目录 一、功能需求及实现 1、功能设计及实现 2、软硬件需求…

GitLab CI Runner安装

参考文章&#xff1a;[花了两天&#xff0c;搞了Gitlab-Runner CI/CD实现自动化部署&#xff0c;可比Jenkins香太多啦&#xff01;&#xff01;&#xff01;&#xff01;_gitlab的cicd取代jenkens-CSDN博客] Gitlab的CI需要安装CI专用的GitLab Runner&#xff0c;否则跑不起来…

优秀的安防视频监控平台应该具备怎样的视频编解码能力?

随着安防技术的飞速发展&#xff0c;监控平台作为保障公共安全、维护社会秩序的重要工具&#xff0c;其性能与效率日益成为行业关注的焦点。其中&#xff0c;监控平台的视频编码能力在视频监控系统中扮演着至关重要的角色&#xff0c;视频编码技术作为监控系统的核心组成部分&a…

基于JAVA+SpringBoot+Vue的中药实验管理系统

基于JAVASpringBootVue的中药实验管理系统 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末附源码下载链接&#x1f345; 哈…

探究文本完全对齐技术:从理论到代码

文本完全对齐算法解析与实现 引言 在编辑文档、设计书籍版面或网页时&#xff0c;通常需要将文本进行格式化对齐&#xff0c;以提升视觉吸引力和易读性。 一种广泛采用的对齐技术是所谓的“完全对齐”&#xff0c;这意味着文本的每一行的起始和结束位置都要对齐整齐。 虽然许多…

湖仓一体-Paimon篇-简介

什么是Paimon&#xff1f; 2021年末&#xff0c;Flink官方提出打造一个全新的存储 Flink Table Store&#xff0c;一个 Flink 完全内置的存储。 为了让 Flink Table Store 能够有更大的发展&#xff0c;Flink PMC经过讨论决定将其捐赠Apache进行独立孵化。 2023 年 3 月 12 日…

《信息系统安全》课程实验指导

第1关&#xff1a;实验一&#xff1a;古典密码算法---代换技术 任务描述 本关任务&#xff1a;了解古典密码体制技术中的代换技术&#xff0c;并编程实现代换密码的加解密功能。 注意所有明文字符为26个小写字母&#xff0c;也就是说字母表为26个小写字母。 相关知识 为了完…

声音之旅:2024四大必备音乐剪辑软件盘点!

音乐剪辑&#xff0c;作为一种艺术形式&#xff0c;让每个人都能够成为自己音乐故事的导演。今天&#xff0c;我们将探索几款优秀的音乐剪辑工具&#xff0c;它们分别是福昕音频剪辑、Audio Trimmer、Ocenaudio和闪电音频剪辑。 福昕音频剪辑 直达链接&#xff1a;www.pdf365…