vue3 使用 watch 时陷入了个直觉陷阱

        场景:在vue中,使用watch 的场景是很常见的。编写业务代码时,需要监听一个或多个值的变化时,经常性会使用watch,日常使用就不提了,直入主题,来一段使用watch的简单代码,有一定前端水平的人应该能立马发现问题。

import { watch, onMounted, ref } from 'vue'const people = ref({ name: '小明', age: 18 })watch(() => [people.value.name],(val, old) => {console.log(val, old, '监听了数组()=>[],   val,old')},{ immediate: true }
)watch(() => people.value.name,(val, old) => {console.log(val, old, '监听了基本类型number()=>,   val,old')},{ immediate: true }
)onMounted(() => {let age = people.value.age// 每2秒年龄+1setInterval(() => {age += 1people.value = {...people.value,age}}, 2000)
})

        创建了一个人叫小明的people变量,每过两秒,小明的年龄都加1,这时候,两段监听函数的区别是,前面是监听了小明名字是数组类型,后面的监听是监听具体小明名字,会打印哪一段?还是两段都打印?还是都不打印?

        注意:这里onMounted里函数的计时器改变的是“年龄”(age),而监听的是“名字”(name)

        打印结果:打印了监听()=>[]

        

其实原因在onMounted函数里改变值的写法,是把整个对象给替换掉了

// 是这样赋值的
people.value = xxx;// 并没有这样赋值
people.value.age  = xxx;

        这就导致存储people.value的值重新被分配了,内存地址发生了改变,但是存储 name 的值却还是原来的,name 引用的内存地址没有改变。回想一下vue3 的监听原理,用的是proxy 监听对象,reflect 反射对象。监听数组时,对数组里的每个object都都进行了一次proxy 监听,当object改变了,则通知订阅者,而监听的的是基本类型时,会监听基本类型的数值有没有被改变。如果这里watch 监听的是的是"age",那不管是数组还是number,都会执行副作用函数。

        会导致什么问题?

举个例子,你有这么一个场景,你的路由地址有n个参数,其中有2个是你需要监听的参数,当监听到者两个参数发生变化时,你可能会这样写:

import { watch, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
const route = useRoute()
const router = useRouter()// 其实我只想监听today和where的变化,才想执行副作用,比如周二游泳,周三跑步
// other改变时并不想执行该副作用
watch(() => [route.query.today, route.query.where],([today, where]: any[]) => {console.log(`today:${today},where:${where}`)doSomething(today, where)},{immediate: true}
)function doSomething(today: string | undefined, where: string | undefined) {// 当只有星期和地址改变的时候,我想执行这个函数console.log(`今天是星期${today},我想去${where}`)
}onMounted(() => {console.log('onMounted')let other = '0'setInterval(() => {other = Number(other) + 1 + ''console.log('other:', other)router.push({path: '/',query: {other,today: '一',where: '公司摸鱼'}})}, 3000)
})

实际情况却是:today和where 没有改变,other变了,天晴了,雨停了,doSomething执行了,我又在摸鱼了

        看了上面监听执行的逻辑性问题,如果你的基础水平不够扎实,你应该避免这种监听一个数组,数组中包含多个对象的值的写法,不要太依赖于watch,watch当然是好用的,只是我们在编写代码的时候,总不可能考虑得太全的。

        解决方案:

        可以分开多个watch 来监听:

                watch(()=>route.query.today,()=>{ doSomething() });

                watch(()=>route.query.where,()=>{ doSomething() });

如果觉得重复代码太多,就是想写数组形式的监听可以吗,可以的;

加一个if判断,if(newValue.today !== oldValue.today){ doSomething() }

        所以,当你想初始化一个变量的时候,要考虑到这个变量有没有监听代码,赋值为 null 时会不会产生相应的问题,它是官方推荐的方法,但可不知道你这是不是官方推荐的写法~

        所以watch监听时,不要太依赖与watch 的副作用执行,请多加一层判断

        

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

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

相关文章

秘密背后的秘密-高速PCB的层叠确认时,工厂为何不写铜箔类型

一博高速先生成员:王辉东 “三面青山一面湖,无尽烟波画舫浮。”说的是巢湖,到了合肥怎能不去巢湖看看呢。 周末休息,大刚说我开车,小胡(丽华)说我也去。 大刚说走就走,秒开车&…

关于使用命令行打开wps word文件

前言 在学习python-docx时,想在完成运行时使用命令行打开生成的docx文件。 总结 在经过尝试后,得出以下代码: commandrstart "C:\Users\86136\AppData\Local\Kingsoft\WPS Office\12.1.0.16929\office6\wps.exe" "./result…

函数的一点点习题

1、利用递归计算0-n的和 #include <stdio.h> #include <string.h> #include <stdlib.h> int rec(int n) {if(n0)return 0;elsereturn nrec(n-1); } int main(int argc, const char *argv[]) {int n0;printf("please enter n:");scanf("%d&quo…

Postgresql配置SSL连接

1、系统需要有openssl、openssl-devel包 yum -y install openssl openssl-devel 2、查看当前数据库是否使用openssl编译 pg_config|grep CONFIGURE 如果没有重新编译 make clean make && make install 3、服务器端证书配置 服务器端需生成三个文件: root.crt(根证…

Vue路由讲解-05

这里的路由并不是指我们平时所说的硬件路由器&#xff0c;这里的路由就是SPA&#xff08;single page application单页应用&#xff09;的路径管理器。再通俗的说&#xff0c;vue-router就是WebApp的链接路径管理系统。 vue-router是Vue.js官方的路由插件&#xff0c;它和vue.j…

免费 逼真:快手“可灵”后又一Sora级选手登场

就在今日&#xff0c;英伟达投资的旧金山初创公司 Luma AI 打出一手王牌&#xff0c;推出新一代 AI 视频生成模型 Dream Machine&#xff0c;可以文生视频&#xff0c;图生视频&#xff0c;人人免费可用。同时&#xff0c;Luma AI 称 Dream Machine 可以从文本和图像生成“高质…

什么品牌洗地机性价比高?四大出色的王牌机型力荐

科技的发展让咱们的生活变得更加便捷&#xff0c;很多智能清洁家电的出现&#xff0c;例如洗地机&#xff0c;集合了扫地、吸尘、拖地、除菌的功能&#xff0c;帮助了我们高效地完成了家务活&#xff0c;给我们腾出了更多享受生活的时间。但&#xff0c;相信有不少的新手朋友们…

XSKY 在金融行业:新一代分布式核心信创存储解决方案

近日&#xff0c;国家金融监督管理总局印发了《关于银行业保险业做好金融“五篇大文章”的指导意见》&#xff0c;在数字金融领域提出明确目标&#xff0c;要求银行业保险业数字化转型成效明显&#xff0c;数字化经营管理体系基本建成&#xff0c;数字化服务广泛普及&#xff0…

SaaS案例分享:成功构建销售渠道的实战经验

面对SaaS产品推广的难题&#xff0c;你是否曾感到迷茫&#xff0c;不知如何选择有效的销售渠道&#xff1f;Shopify独立站联盟营销或许能为你提供新的思路。Shopify作为领先的电商解决方案提供商&#xff0c;其独立站功能为众多商家提供了强大的在线销售平台。而联盟营销&#…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 生成哈夫曼树(100分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 📎在线评测链接 生成哈夫曼树(100分) 🌍 评测功能需要订阅专栏后私信联系清…

如何应对缺失值带来的分布变化?探索填充缺失值的最佳插补算法

本文将探讨了缺失值插补的不同方法&#xff0c;并比较了它们在复原数据真实分布方面的效果&#xff0c;处理插补是一个不确定性的问题&#xff0c;尤其是在样本量较小或数据复杂性高时的挑战&#xff0c;应选择能够适应数据分布变化并准确插补缺失值的方法。 我们假设存在一个…

【Java】已解决:Java.lang.OutOfMemoryError: GC overhead limit exceeded

文章目录 问题背景可能出错的原因错误代码示例正确代码示例注意事项 问题背景 java.lang.OutOfMemoryError: GC overhead limit exceeded 是Java虚拟机&#xff08;JVM&#xff09;在运行时遇到的一种内存溢出错误。这种错误通常发生在应用程序的堆内存&#xff08;Heap Memor…

香港Web3时代:比特币可以成为「收益性资产」吗?

原文标题&#xff1a;《CAN BITCOIN BE A PRODUCTIVE ASSET?》撰文&#xff1a;Pascal Hgli编译&#xff1a;Chris&#xff0c;Techub News本文来源香港Web3媒体 Techub News 比特币正在经历一场大的变化&#xff0c;人们对其性质有不同的看法。有些人将其视为日常交易的货币…

数据结构试题 16-17

先这样吧&#xff0c;&#xff0c;专业课不是统考&#xff0c;我发现每年的卷子风格都不太一样&#xff0c;侧重点也不一样。以及21的和16的发生了很大的改变。等明年1月再看看吧 那就先over啦 数据结构撒花&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&am…

基于single flight来解决缓存击穿

目录 1. 缓存击穿2. 常见解决方案3.single flight方式3.1 模拟业务场景3.2 使用single flight的方式 缓存雪崩、缓存击穿、缓存穿透不单单是缓存领域的经典场景&#xff0c;更是面试当牛马时必备&#xff08;背&#xff09;八股文。 我们来讨论下缓存击穿场景下的解决方案。 …

【AI开发】RAG基础

RAG的基本流程&#xff1a; 用一个loader把knowledge base里的知识做成一个个的document&#xff0c;然后把document切分成snippets&#xff0c;把snippets通过embedding&#xff08;比如openai的embedding模型或者huggingface的&#xff09;向量化&#xff0c;存储到vectordb…

git 配置私人令牌

这里写自定义目录标题 获取私人令牌配置个人令牌 获取私人令牌 在个人设置里点击私人令牌选型&#xff0c;之后生成令牌即可。注意&#xff1a;令牌只会出现一次&#xff0c;务必保存好。 配置个人令牌 个人令牌&#xff1a;3c15c866fa61066212a83c66fd8133ba # 进入项目文…

护眼灯对眼睛有伤害吗?千万要小心的行业四大弊端内幕

护眼灯&#xff0c;作为现代家居与办公环境中不可或缺的照明伴侣&#xff0c;因其普及性广受青睐。然而&#xff0c;随着大众对视觉健康意识的逐渐增强&#xff0c;一个疑问悄然滋生&#xff1a;护眼灯对眼睛有伤害吗&#xff1f;这一问题不仅触及到了人们对视觉健康的深层担忧…

MLOps模型部署的三种策略:批处理、实时、边缘计算

机器学习运维&#xff08;MLOps&#xff09;是一组用于自动化和简化机器学习&#xff08;ML&#xff09;工作流程和部署的实践。所选择的部署策略可以显著影响系统的性能和效用。所以需要根据用例和需求&#xff0c;采用不同的部署策略。在这篇文章中&#xff0c;我们将探讨三种…

Java家政预约系统源码 家政上门APP源码 家电安装、维修、清洗、美容系统源码、家政系统各端功能细分

Java家政预约系统源码 家政上门APP源码 家电安装、维修、清洗、美容系统源码、家政系统各端功能细分 家政服务系统是一种提供家政服务的系统&#xff0c;它可以为客户提供上门家庭清洁、钟点工、保姆、月嫂、育婴师、护理员等家政服务。节省时间和成本&#xff0c;提高效率&…