从同步到异步:Vue 3 的异步更新策略与 `tick` 机制
1. 引言:Vue 3 的异步更新,我们真的了解吗?
在日常开发中,我们都知道 Vue 3 是异步更新的。大多数时候,我们只是简单地使用 ref、reactive、computed 等 API,享受着 Vue 的响应式系统带来的便利。然而,当我们在某些场景,忽略“异步”更新的底层逻辑,就会导致和预期不相符的问题。
最近,我在一个项目中遇到了一个关于 computed 的问题,这让我重新审视了 Vue 3 的异步更新机制。下面,我将分享这段经历,希望能帮助大家更好地理解 Vue 3 的异步更新策略。
2. 问题背景:computed 的二次转换与异步更新的冲突
在项目中,我需要对一个响应式数据进行二次转换,以便在模板中使用。为了分离逻辑,我使用了 computed 来实现这个转换。
整个问题涉及到3个文件:
index.vue
Temp.vue
useSearchParam.ts
在index.vue中,使用Temp.vue模块和useSearchParam。然后在index.vue中,通过computed,来处理和searchParam相关的转换逻辑。
代码大致如下:
index.vue
<template><Temp ref="tempRef" :param="computedParam"/>
</template>
<script setup lang="ts">
...
const { searchParam } = useSearchParam(()=>{tempRef.value.load();
});
const computedParam = computed(() => {return {businessCode: `computed businessCode:${searchParam.businessCode}`};
});
</script>
在 Temp.vue 组件中,我通过 props 接收 computedParam,并在 load 方法中打印 businessCode:
Temp.vue
<template><span>{{ param.businessCode }}</span>
</template>
<script lang="ts" setup>
interface Props {param: any
}
const props = defineProps<Props>();
const load = () => {console.log("temp-load-1", props.param.businessCode);...
};
defineExpose({ load });
</script>
在 useSearchParam.ts 中,我通过异步加载数据并更新 searchParam:
useSeachParam.ts
export function useSearchParam(dataLoaded: Function) {const searchParam = reactive({});onMounted(async () => {const result = await store.businessNames.load({}));searchParam["businessCode"] = first(result)?.code;dataLoaded && dataLoaded();});
}
然而,当 businessNames 加载完成后,temp-load-1 打印出来的 businessCode 是 undefined,而在span中却正常渲染出来了businessCode的值。这让我感到困惑,为什么没有获取到最新的 computedParamcomputed 值?
3. 问题剖析:computed 的惰性求值与异步更新的冲突
通过分析,我发现问题的根源在于 computed 的惰性求值机制。computed 只有在被访问时才会重新计算,而在异步更新中,computed 不会立即重新计算,导致在同步代码中获取到旧的值。
具体来说,当 searchParam.businessCode 被更新时,Vue 会标记 computedParam 为“脏”状态,但不会立即重新计算。只有在 computedParam 被访问时,Vue 才会重新计算并返回最新的值。然而,dataLoaded是一个同步函数(关键之处),当它触发了Temp里面的load方法时,computedParam 还没有被重新计算,导致 props.param.businessCode 仍然是 undefined。
4. 解决方案:使用 nextTick 确保 computed 的更新
为了解决这个问题,我调整了 useSearchParam.ts 中的代码,将 dataLoaded 回调函数放入 nextTick 中执行:
onMounted(async () => {const result = (await store.businessNames.load({})) as BusinessNameItem[];searchParam["businessCode"] = first(result)?.code;nextTick(() => {dataLoaded && dataLoaded();});
});
通过这种方式,dataLoaded 回调函数会在 Vue 的下一个 tick 中执行,此时 searchParam 的更新已经完成,computedParam 也已经重新计算,并返回了最新的值。因此,temp-load-1 和 里面一样,都显示出来了相同的正常值。
5. 深入理解:Vue 3 的 tick 机制
通过这次问题的解决,我深入理解了 Vue 3 的 tick 机制。tick 是 Vue 完成一次响应式数据更新和 DOM 渲染的过程。Vue 会将所有的响应式数据更新和 DOM 更新批量处理,并在下一个事件循环的 tick 中执行。
在 nextTick 中,Vue 会完成所有响应式数据的更新和 DOM 的渲染,确保回调函数在最新的状态下执行,具体到这个问题中,computedParam已经完成了更新。因此,通过 nextTick,我们可以确保在异步更新后获取到最新的computedParam的 computed 值。
6. 总结:从同步到异步,理解 Vue 3 的异步更新策略
通过这次经历,我们不仅解决了 computed 的异步更新问题,还深入理解了 Vue 3 的 tick 机制。Vue 3 的异步更新策略虽然复杂,但通过合理使用 nextTick,我们可以确保在异步更新后获取到最新的数据。
在日常开发中,我们应该更加关注 Vue 3 的异步更新策略,尤其是在使用 computed 和 watch 时,确保数据的更新和渲染顺序正确。通过这种方式,我们可以编写出更加高效和可靠的 Vue 3 代码。
相关文章:
从同步到异步:Vue 3 的异步更新策略与 `tick` 机制
1. 引言:Vue 3 的异步更新,我们真的了解吗? 在日常开发中,我们都知道 Vue 3 是异步更新的。大多数时候,我们只是简单地使用 ref、reactive、computed 等 API,享受着 Vue 的响应式系统带来的便利。然而&…...
2024中国信通院“集智”蓝皮书合集(附下载)
【目 录】 1. 数字政府一体化建设蓝皮书(2024年) 2. 数字乡村发展实践蓝皮书(2023年) 3. 中国工业互联网发展成效评估报告(2024年) 4. 云计算蓝皮书(2024年) 5. 具身智能发展报告…...
muduo源码阅读:linux timefd定时器
⭐timerfd timerfd 是Linux一个定时器接口,它基于文件描述符工作,并通过该文件描述符的可读事件进行超时通知。可以方便地与select、poll和epoll等I/O多路复用机制集成,从而在没有处理事件时阻塞程序执行,实现高效的零轮询编程模…...
nvm 1.2.2 报错解决方法 The system cannot find the file specified.
安装了最新版本nvn1.2.2后,安装老版本node时报错(安装新版本没问题),报错内容如下: error installing 14.16.0: open C:\Users\admin\AppData\Local\Temp\nvm-npm-430098699\npm-v6.14.11.zip: The system cannot fin…...
学习Python的基本入门知识
学习Python的入门知识可以从以下几个方面开始: ### 1. **Python简介** - **Python** 是一种高级、解释型、通用的编程语言,由Guido van Rossum于1989年发布。 - 它以简洁、易读的语法著称,适合初学者。 - 广泛应用于Web开发、数据分…...
web安全——分析应用程序
文章目录 一、确定用户输入入口点二、确定服务端技术三、解析受攻击面 一、确定用户输入入口点 在检查枚举应用程序功能时生成的HTTP请求的过程中,用户输入入口点包括: URL文件路径 通常,在查询字符?之前的URL部分并不视为用户输入入口&am…...
OpenEuler学习笔记(三十五):搭建代码托管服务器
以下是主流的代码托管软件分类及推荐,涵盖自托管和云端方案,您可根据团队规模、功能需求及资源情况选择: 一、自托管代码托管平台(可私有部署) 1. GitLab 简介: 功能全面的 DevOps 平台,支持代码托管、C…...
平台设备驱动之gpio子系统(写驱动实现在/sys/...目录下用echo命令点灯)
1、 关键函数(include/linux 及 driver目录下) module_platform_driver(leds_drv); //平台设备驱动入口//获取匹配成功后设备树节点中的 property of_get_named_gpio_flags(node, "led_gpio", 0, &flags); //在/sys/目录下创建文…...
PS渐变工具
渐变工具:(颜色条 起点到终点 为 前景色到背景色) 渐变shift:垂直、水平、45度 渐变工具–》仿色:让渐变变得细腻。仿色值高,过渡柔和,仿色值低,过渡粗糙 渐变工具–》渐变编辑器&am…...
JavaScript将:;隔开的字符串转换为json格式。使用正则表达式匹配键值对,并构建对象。多用于解析cssText为style Object对象
// 使用正则表达式匹配键值对,并构建对象 let string2Json(s)>{const r {};s.replace(/;/g, ;).replace(/\;/g, \n).replace(/:/g, :).replace(/\n/g, \n)//合并多个换行符.split(\n).forEach(item > {const [k, v] item.split(:);(k…...
2025年追觅科技社招校招入职测评北森题库商业推理测试内容与技巧
在追觅科技的招聘流程中,无论是校园招聘还是社会招聘,应聘者都需要通过北森测评题库的商业推理部分。这部分的测评旨在评估应聘者的商业推理能力,是评估考生综合能力的重要工具。考试时间为40分钟,需要完成28题,题型以…...
AI大模型-提示工程学习笔记19-自我反思
目录 1. 自我反思的核心思想 (1) LLM 的局限性 (2) Reflexion 的解决方案 2. Reflexion 的工作流程 (1) 任务输入 (2) 初始生成 (3) 反思 (Reflection) (4) 调整与改进 (5) 迭代 (6) 结果输出 3. Reflexion 的关键组件 (1) 大语言模型 (LLM) (2) 反思者 (Reflector…...
【工具变量】公司企业数字领导力(2004-2023年)
数据简介:企业数字化领导力是指在数字经济时代,领导者通过战略性地使用数字资产、引领组织变革,使企业在数字化环境中获得持续成功的能力。对于上市公司而言,这种领导力尤为重要,因为它直接关系到企业的战略方向、市场…...
Android 10.0 Settings中系统菜单去掉备份二级菜单
1.前言 在10.0的系统rom定制化开发中,在系统Settings开发过程中,会发现在settings中的系统菜单中需要去掉 备份这个菜单,接下来就需要分析下系统菜单中的备份菜单的相关功能,然后实现去掉备份菜单的功能 2.Settings中系统菜单去掉备份二级菜单的核心类 packages/apps/Se…...
C++ | 设计模式 | 代理模式
代理模式(Proxy Pattern) 代理模式是一种结构型设计模式 ,它为某个对象提供一个代理,以控制对该对象的访问。代理模式可以在不改变原始对象的情况下,通过引入代理对象来扩展功能或控制对原始对象的访问。 核心思想 代…...
【Vue工作原理】VueCli4 模板文件template不存在会生产一个默认文件原理
Vue CLI 4 的 HtmlWebpackPlugin 在模板文件缺失时,不会中断构建流程,而是自动生成一个极简 HTML 结构(DeepSeek回答) 📘 官方资料来源解析(基于 2025 年存档数据) 当前时间&#…...
数据开发的简历及面试
简历 个人信息: 邮箱别写QQ邮箱, 写126邮箱/189邮箱等 学历>>本科及以上写,大专及以下不写 专业>>非计算机专业不写 政治面貌>>党员写, 群众不用写 掌握的技能: 精通 > 熟悉 > 了解 专业工具: 大数据相关的 公司: 如果没有可以写的>>金融服…...
如何在docker上部署前端nginx服务(VUE)
目录结构 clean.sh docker stop rszWeb; docker rm rszWeb; start.sh docker run -d \ --name rszWeb \ -p 7084:80 \ -m 500m \ --privileged=true \ --restart=always \ -v /home/rsz/ui/conf/nginx.conf:/etc/nginx/nginx.conf \ -v /home/rsz/ui/logs:/meta/logs \ -v /…...
模型和数据集的平台之在Hugging Face上进行模型下载、上传以及创建专属Space
模型下载 步骤: 注册Hugging Face平台 https://huggingface.co/ 新建一个hf_download_josn.py 文件 touch hf_download_josn.py 编写hf_download_josn.py文件 import os from huggingface_hub import hf_hub_download# 指定模型标识符 repo_id "inter…...
[Web 信息收集] Web 信息收集 — 手动收集 IP 信息
关注这个专栏的其他相关笔记:[Web 安全] Web 安全攻防 - 学习手册-CSDN博客 0x01:通过 DNS 服务获取域名对应 IP DNS 即域名系统,用于将域名与 IP 地址相互映射,方便用户访问互联网。对于域名到 IP 的转换过程则可以参考下面这篇…...
排序算法(3):
这是我们的最后一篇排序算法了,也是我们的初阶数据结构的最后一篇了。 我们来看,我们之前已经讲完了插入排序,选择排序,交换排序,我们还剩下最后一个归并排序,我们今天就讲解归并排序,另外我们还…...
TypeScript - 泛型
泛型允许在定义函数、类或接口时,使用类型参数来表示未指定的类型,这些参数在具体使用时,才被指定具体的类型,泛型能让同一段代码适用于多种类型,同时仍然保持类型的安全性。 举例:如下代码中 <T> 就…...
Python基于Django和Vue的校园互助平台(附源码、文档说明)
博主介绍:✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇dz…...
打包rocketmq-dashboard报错问题记录
在进入到\rocketmq-dashboard-2.0.0\rocketmq-dashboard-rocketmq-dashboard-2.0.0目录下,执行mvn clean package -Dmaven.test.skiptrue打包,报错: java: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does…...
Redis 高可用性:如何让你的缓存一直在线,稳定运行?
🎯 引言:Redis的高可用性为啥这么重要? 在现代高可用系统中,Redis 是一款不可或缺的分布式缓存与数据库系统。无论是提升访问速度,还是实现数据的高效持久化,Redis 都能轻松搞定。可是,当你把 …...
Windows和AD域提权枚举脚本及工具介绍
在 Windows 和 Active Directory (AD) 域环境中,权限提升和枚举是渗透测试的关键部分。为了有效进行这些操作,使用特定的工具和脚本可以帮助你识别和利用系统中的漏洞。以下是一些常用于 Windows 和 AD 域环境中的权限提升和枚举脚本工具: W…...
【Linux】调试工具GDB的使用及案例讲解
Linux系列 文章目录 Linux系列前言一、gdb的使用背景二、gdb的使用总结 本篇主要针对小白讲解,可以很多地方比较咯嗦 前言 GDB是Linux下一款强大的调试工具。GDB可以调试C、C、Java等语言,对于在Linux下工作的程序员来说,GDB是必不可少的调试…...
DeepSeek回答:AI时代Go语言学习路线
最近有小伙伴经常会问:**该如何学习入门Go语言?怎样提升Go语言Coding水平?**这篇文章我们就使用DeepSeek来梳理下Go语言在AI时代的学习路线。 向DeepSeek提问的问题原文: 你现在是一名资深的Go语言工程师,精通Go语言并…...
1分钟用DeepSeek编写一个PDF转Word软件
一、引言 如今,在线工具的普及让PDF转Word成为了一个常见需求,常见的pdf转word工具有收费的wps,免费的有pdfgear,见下文: PDFgear:一款免费的PDF编辑、格式转化软件-CSDN博客 还有网上在线的免费pdf转word工具smallp…...
【Linux】初探信号的奥秘
目录 一、引入信号: 1、什么是信号: 二、前后台进程: 三、信号的处理方式: 四、键盘数据与信号: 前言: 在Linux系统编程中,信号(Signal)是一种至关重要的进程间通信…...
