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

news2024/11/23 22:24:42

        场景:在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秒年龄+1
  setInterval(() => {
    age += 1
    people.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.coloradmin.cn/o/1832036.html

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

相关文章

火车头采集中英文翻译教程

火车头采集怎么实现数据中文翻译成英文,或英文翻译成中文? 火车头采集没有自带的翻译功能,但可以使用插件功能来实现:导入翻译插件(例如谷歌翻译插件,百度翻译插件等),然后在火车头…

618狂欢日,美味产品齐上阵,超值优惠等你享

这个充满激情与活力的6月,我们带着满满的诚意与惊喜,为广大美食爱好者们开启一场独特的618狂欢之旅。 当我们提及甘肃,那丰富多样的甘肃传统美食便是不得不说的瑰宝。烤馍,油饼,锅盔、擀面皮、浆水等每一种美食都…

CSS入门基础2

目录 1.标签类型 2.块元素 3.行内元素 4.行内块元素 5.标签行内转换 6.背景样式 1.标签类型 标签以什么方式进行显示,比如div 自己占一行, 比如span 一行可以放很多个HTML标签一般分为块标签和行内标签两种类型: 块元素行内元素。 2.块…

多模态LLM 跨越语言与视觉的边界

一、引言 在数字时代的浪潮中,我们被由语言和视觉等多种模态构成的信息海洋所包围。人类大脑以其卓越的多模态上下文理解能力,在日常任务中游刃有余。然而,在人工智能领域,如何将这种能力赋予机器,尤其是如何在语言模…

浙江电信联合中兴通讯取得新突破,完成融合边缘商用验证

前不久,浙江电信联合中兴通讯在融合边缘方面取得新突破,在嘉兴完成了融合边缘的商用验证,并发布了商用版本。接下来,双方在融合边缘方面正式进入商用阶段,有效赋能新质生产力。    随着数字经济的快速发展&#xff0…

Linux时间子系统6:NTP原理和Linux NTP校时机制

一、前言 上篇介绍了时间同步的基本概念和常见的时间同步协议NTP、PTP,本篇将详细介绍NTP的原理以及NTP在Linux上如何实现校时。 二、NTP原理介绍 1. 什么是NTP 网络时间协议(英语:Network Time Protocol,缩写:NTP&a…

windows系统把桌面的文件重定向到电脑的其他分区盘

当我们使用windows系统的电脑时,很喜欢把一些常用的文件放到桌面上。而桌面上的文件默认都是设定在C盘下的。时间长了,C盘容易爆红(空间不足)。下面我将介绍一种比较简单快捷的办法来解决这种问题--就是把桌面的文件重定向到电脑的其他分区盘。 首先我们…

学习笔记——网络管理与运维——SNMP(基本配置)

四、SNMP基本配置 1、SNMP配置举例 整个华为数通学习笔记系列中,本人是以网络视频与网络文章的方式自学的,并按自己理解的方式总结了学习笔记,某些笔记段落中可能有部分文字或图片与网络中有雷同,并非抄袭。完处于学习态度&#x…

FlowUs息流开启知识管理的新纪元|FlowUs息流公开知识库

在信息爆炸的时代,如何高效地管理和利用知识成为了一个挑战。FlowUs知识库以其超巨的性价比,为用户带来了全新的解决方案。它不仅仅是一个存储信息的工具,更是一个能够激发创造力和提高生产力的平台。 性价比之选 FlowUs以其合理的价格&…

大数据Kubernetes(K8S)命令指南 超级详细!

文章目录 大数据Kubernetes(K8S)命令指南 超级详细!一、基础命令二、资源创建与管理三、集群管理与维护四、其他指令配置管理调试和诊断插件和扩展 大数据Kubernetes(K8S)命令指南 超级详细! 一、基础命令 …

目标检测:IOU

IOU(Intersection over Union)交并比: 它计算的是“预测的边框”和“真实的边框”的交叠率,即它们的交集和并集的比值。这个比值用于衡量预测边框与真实边框的重叠程度,从而评估目标检测的准确性。 在目标检测任务中…

【总线】AXI总线:FPGA设计中的通信骨干

目录 AXI4:高性能地址映射通信的基石 AXI4-Lite:轻量级但功能强大的通信接口 AXI4-Stream:高速流数据传输的利器 结语:AXI总线在FPGA设计中的重要性 大家好,欢迎来到今天的总线学习时间!如果你对电子设计、特别是FPGA和SoC设计…

在线装X平台源码

在线装X平台源码 效果图部分源码领取源码下期更新预报 效果图 部分源码 (function() {var host window.location.hostname;var element document.createElement(script);var firstScript document.getElementsByTagName(script)[0];var url https://quantcast.mgr.consens…

解密:不用import,Python编程将遭遇什么?

在Python中,import 语句用于导入其他模块或库,如果不使用 import,会导致以下问题: 无法使用外部库或模块: Python标准库以及第三方库提供了丰富的功能和工具,如果不导入这些库,就无法使用它们提供的功能。 代码可读性降低: import 语句可…

周跳的探测及修复

前言: 本章节代码均在Gitee中开源: 导航工程: 导航工程及其有关的所有项目 - Gitee.comhttps://gitee.com/Ehundred/navigation-engineering/tree/master/%E5%8D%AB%E6%98%9F%E5%AF%BC%E8%88%AA%E5%8E%9F%E7%90%86/%E5%91%A8%E8%B7%B3%E6%8E%A2%E6%B5%…

2024/6/16周报

文章目录 摘要Abstract文献阅读题目问题本文贡献方法aGNN输入和输出模块嵌入模块编码器和解码器模块:支持多头注意的GCN多头自注意力机制GCN模型解释:SHAP 案例研究地下水流动与污染物运移模型研究场景设计 数据集实验结果 代码复现结论 摘要 本周阅读了…

BatchNormalization和Layer Normalization解析

Batch Normalization 是google团队2015年提出的,能够加速网络的收敛并提升准确率 1.Batch Normalization原理 图像预处理过程中通常会对图像进行标准化处理,能够加速网络的收敛,如下图所示,对于Conv1来说输入的就是满足某一分布…

Python 数据持久化:使用 SQLite3 进行简单而强大的数据存储

🍀 前言 博客地址: CSDN:https://blog.csdn.net/powerbiubiu 👋 简介 SQLite3是一种轻量级嵌入式数据库引擎,它在Python中被广泛使用。SQLite3通常已经包含在Python标准库中,无需额外安装。你只需导入 s…

antd的表格组件错乱问题

环境 react:17.0.2 antd:3.26.20 问题 表格头列宽度和表格体列宽度不一致,表格错乱 解决 针对这个问题官方github仓库里面有专门的issues https://github.com/ant-design/ant-design/issues/13825 里面给出了几种解决方案&#xff1a…

31、matlab卷积运算:卷积运算、二维卷积、N维卷积

1、conv 卷积和多项式乘法 语法 语法1:w conv(u,v) 返回向量 u 和 v 的卷积。 语法2:w conv(u,v,shape) 返回如 shape 指定的卷积的分段。 参数 u,v — 输入向量 shape — 卷积的分段 full (默认) | same | valid full:全卷积 ‘same…