20240628每日前端---------解决vue项目滥用watch
主题
滥用watch。
名字解释
watch
例子
先看一个代码例子:
<template>{{ dataList }}
</template><script setup lang="ts">
import { ref, watch } from "vue";const dataList = ref([]);
const props = defineProps(["disableList", "type", "id"]);
watch(() => props.disableList,() => {// The logic based on disableList is very complex, and it computes a new list synchronouslyconst newList = getListFromDisabledList(dataList.value);dataList.value = newList;},{ deep: true }
);
watch(() => props.type,() => {// The logic based on type is very complex and computes a new list synchronouslyconst newList = getListFromType(dataList.value);dataList.value = newList;}
);
watch(() => props.id,() => {// Fetch dataList from the serverfetchDataList();},{ immediate: true }
);
</script>
在上面的示例中,当props.id被更新或者初始化时候,dataList会从服务器异步获取。
当disableList,type更新时,将同步计算新的 dataList。
代码逻辑流程图如下:

乍一看,上面的代码似乎很好,但是当不熟悉这个模块的新同事接手时,问题就出现了。
通常,在接管我们不熟悉的业务领域时,我们需要找到一个起点。
对于前端方面哈,这个起点肯定是浏览器中呈现的页面。
在 Vue 中,页面是从模板渲染的,因此识别模板中使用的变量及其来源可以帮助我们理解业务逻辑。
以变量disableList为例,追溯其来源通常可以明确业务逻辑。
在我们的例子中,来源是多种多样的,且来自多个来源。
首先,它通过 watch props.id 从服务器异步更新。
然后,它通过监听watch props.disableList 和 watch props.type 上实现同步更新。
此时,不熟悉业务的同事收到产品要求以更新检索逻辑时,必须首先熟悉其多个来源背后的逻辑。
在了解了逻辑之后,他们需要准确分析哪些应该修改以满足产品要求。
然而,在实践中,在维护别人的代码(尤其是复杂代码)时,我们通常不愿意修改现有代码,而是在上面添加我们自己的代码。
更改别人的复杂代码可能会引入错误,然后我们可能会受到指责。因此,我们通常的方法是添加另一个并实现最新的业务逻辑:
watch(() => props.xxx,() => {// Add the latest business logicconst newList = getListFromXxx(dataList.value);dataList.value = newList;}
);
经过几次迭代后,此文件变得杂乱无章,充斥着大量语句,从而导致“屎山代码”。当然,在某些情况下,这种编码风格可能是故意确保自己在团队中的地位,因为没有人敢碰这个复杂的代码块。。。。。。。
如何解决问题 computer
首先我们先明白正确的可维护的变量流程

dataList在模板中,同步更新,数据异步从服务器获取。
整个过程可以可视化为单个线程。当新开发人员加入团队迭代相关业务时,只需要了解最新的产品需求是建议在同步阶段还是异步阶段修改代码,然后在对应阶段添加最新的代码即可。
基于以上逻辑,代码简写如下:
<template>{{ renderDataList }}
</template>
<script setup lang="ts">
import { ref, computed, watch } from "vue";
const props = defineProps(["disableList", "type", "id"]);
const dataList = ref([]);
const renderDataList = computed(() => {// Calculate the list based on disableListconst newDataList = getListFromDisabledList(dataList.value);// Calculate the list based on typereturn getListFromType(newDataList);
});
watch(() => props.id,() => {// Fetch dataList from the serverfetchDataList();},{immediate: true,}
);
</script>
在上面中,我们不再渲染dataList变量,而是渲染renderDataList变量。 是包含dataList的所有同步相关逻辑的 。代码逻辑流程图如下:

这样,如果有新需求变量变更,修改逻辑的演示如下:
const renderDataList = computed(() => {// Add the latest business logic from the productconst xxxList = getListFromXxx(dataList.value);// Calculate the list based on disableListconst newDataList = getListFromDisabledList(xxxList);// Calculate the list based on typereturn getListFromType(newDataList);
});
结论
本文介绍了两种主要的使用场景:一种是当被监视的值发生变化并需要同步更新要渲染的值时,另一种是当值发生变化并需要从服务器异步获取要渲染的值时。
如果同步和异步更新都不加区别地写在watch中,那么接手的后续维护者会发现梳理相关逻辑非常痛苦。
这是因为到处都在更新值,完全不清楚在哪里添加最新的业务逻辑。
随着时间的流逝,如果代码变成一堆实例,可维护性就会恶化。
我们的优化解决方案是将所有同步更新的代码堆叠到renderDataList
后续维护者只需要决定新业务是否是同步更新,那么他们就应该在dataList中写入新的业务逻辑。
如果是对 renderDataList的异步更新,则应将新的业务逻辑写入 computed中。
题外话
那么vue中 watch 和computer的区别你知道了吗?
1、缓存机制:
computed属性具有缓存机制。只有当其依赖的数据发生变化时,它才会重新计算。如果依赖的数据没有变化,那么它将直接返回之前缓存的结果。这种缓存机制可以提高性能,避免不必要的计算。
watch属性则没有缓存机制。每当它所监听的数据发生变化时,它都会触发相应的操作,不论这个操作是否已经被执行过。
2、异步支持:
computed不支持异步操作。如果computed内部包含异步操作,它将无法正常工作,因为它依赖于同步的响应式依赖。
watch则支持异步操作。在watch的回调函数中,你可以执行任何异步操作,如网络请求等。
3、执行时机:
computed属性在依赖的数据发生变化时才会执行。如果数据没有变化,那么它将不会执行。
watch属性则会在所监听的数据发生变化时立即执行其回调函数。
4、数据类型:
computed主要用于处理复杂的逻辑运算,返回一个新的属性值。它通常用于处理一些需要通过计算得到的数据,如根据购物车中的商品数量和单价计算出总价等。
watch则主要用于监听数据的变化,并在数据变化时执行一些副作用或异步操作。例如,根据用户输入的地址获取并显示地图信息等。
5、参数和返回值:
computed属性通常不需要额外的参数,它直接返回一个新的属性值。同时,它也可以定义一个setter函数来修改它的值。
watch属性则需要两个参数:newVal(新值)和oldVal(旧值)。在watch的回调函数中,你可以使用这两个参数来执行相应的操作。
6、性能:
由于computed具有缓存机制,因此它在处理大量数据或复杂计算时通常具有更好的性能。
watch则没有缓存机制,因此在处理大量数据或频繁变化的数据时可能会导致性能问题。
相关文章:
20240628每日前端---------解决vue项目滥用watch
主题 滥用watch。 名字解释 watch 例子 先看一个代码例子: <template>{{ dataList }} </template><script setup lang"ts"> import { ref, watch } from "vue";const dataList ref([]); const props defineProps([&q…...
【LLM 评估】GLUE benchmark:NLU 的多任务 benchmark
论文:GLUE: A Multi-Task Benchmark and Analysis Platform for Natural Language Understanding ⭐⭐⭐⭐ arXiv:1804.07461, ICLR 2019 Site: https://gluebenchmark.com/ 文章目录 一、论文速读二、GLUE 任务列表2.1 CoLA(Corpus of Linguistic Accep…...
Go线程调度器
基本结构 字段gcwaiting、stopwait和stopnoted都是串行运行时任务执行前后的辅助协调手段 gcwaiting字段的值用于表示是否需要停止调度 在停止调度前,该值会被设置为1在恢复调度之前,该值会被设置为0这样做的作用是,一些调度任务在执行时只…...
使用 fvm 管理 Flutter 版本
文章目录 Github官网fvm 安装Mac/Linux 环境Windows 环境 fvm 环境变量fvm 基本命令 Github https://github.com/leoafarias/fvmhttps://github.com/flutter/flutter 官网 https://fvm.app/ fvm 安装 Mac/Linux 环境 Install.sh curl -fsSL https://fvm.app/install.sh …...
若依-前后端分离项目学习
★★★★★省流 直接看第一集和最后一集★★★★★ 第一天(6.24) 具体参考视频 b站 楠哥教你学Java 【【开源项目学习】若依前后端分离版,通俗易懂,快速上手】 https://www.bilibili.com/video/BV1HT4y1d7oA/?shar…...
使用adb shell getprop命令获取Android设备的属性
常用属性获取: adb shell getprop ro.build.version.emui —查询EMUI版本 adb shell getprop ro.product.brand —查询手机品牌 adb shell getprop ro.product.name --查询设备名称 adb shell getprop ro.serialno —查询设备序列号 获取手机系统信息( CPU,厂商…...
LNMP环境部署指南
本文档将指导您在CentOS 6.5上部署LNMP(Linux、Nginx、MySQL、PHP)环境。 系统环境 系统平台:CentOS release 6.5 安装前准备 在安装LNMP之前,您需要安装一些编译器和依赖包。 必备编译器和工具 #安装gcc、gcc-c编译器&#…...
[stm32]温湿度采集与OLED显示
一、I2C总线协议 I2C(Inter-integrated circuit )是一种允许从不同的芯片或电路与不同的主芯片通信的协议。它仅用于短距离通信,是一种用于两个或多个设备之间进行数据传输的串行总线技术,它可以让你在微处理器、传感器、存储器、…...
大模型知识库的使用
大模型知识库的使用通常涉及以下几个方面,使用大模型知识库可以提高信息检索的准确性和效率,促进知识的传播和应用。同时,也需要关注知识库的质量和更新,以确保提供的知识是准确和可靠的。北京木奇移动技术有限公司,专…...
Docker - Oracle Database 23ai Free
博文目录 文章目录 说明命令NavicatSYSTEMPDBADMIN 扩展公共用户本地用户 说明 Oracle 官方镜像仓库 Database 23ai Free | Oracle Docker 官方没有提供 Oracle Database 相关镜像, 但是 Oracle 官方镜像仓库有提供, 打开上面的链接, 选择 Database, 选择合适的版本, 如 enter…...
spring常用方法
1. 读取配置文件信息 方式一: // 获取文件路径 String fileName "application.yaml"; String filePath this.getClass().getClassLoader().getResource(fileName).getPath();BufferedReader bufferedReader new BufferedReader(new FileReader(path)…...
虚拟机能装在移动硬盘里吗安全吗 PD虚拟机迁移到移动硬盘的方法
虚拟机技术的迅速发展为用户提供了更为灵活的跨系统办公方案。许多用户希望在不同的电脑设备上运行相同的虚拟机,同时带来的也有一个问题:虚拟机能否装在移动硬盘里?针对用户的疑问,接下来给大家介绍虚拟机能装在移动硬盘里吗&…...
刷算法Leetcode---7(二叉树篇)(前中后序遍历)
前言 本文是跟着代码随想录的栈与队列顺序进行刷题并编写的 代码随想录 好久没刷算法了,最近又开始继续刷,果然还是要坚持。 二叉树的题目比之前多了好多,就多分几次写啦~ 这是力扣刷算法的其他文章链接:刷算法Leetcode文章汇总 …...
AliyunOS安装Node.js
方法1:dnf软件包安装工具自动安装 最方便的安装方式是通过系统的dnf工具,我测试使用的AliyunOS的版本是Alibaba Cloud Linux 3.2104,具体流程如下: dnf module list nodejs #列出服务器中可以使用的所有nodejs版本确定下来希望安…...
three.js - MeshPhongMaterial材质(实现玻璃水晶球效果)
1、概念 phong网格材质:Mesh - Phong - Material 一种用于具有镜面高光的光泽表面的材质。 它可以模拟,具有镜面高光的光泽表面,提供镜面反射效果。 MeshPhongMaterial: MeshPhongMaterial是一种基于Phong光照模型的材质&#…...
笔记本电脑安装CentOS
正文共:1234 字 24 图,预估阅读时间:2 分钟 前面我们对VPP进行了多次介绍(羡慕!大佬的VPP能达到180G性能,而我的却只有13.5G),可以发现他的很多优点,但是我们也可以发现它…...
ssh转发功能入门
端口转发概述 端口转发,能够将其他TCP端口的网络数据通过SSH链路转发,并且提供了ssh的加密和解密的服务。 ssh端口转发有如下这些优点: 提供了ssh的加密传输,利于安全能够突破防火墙限制 目前ssh端口转发有如下几种方式&#x…...
Listary(Windows 文件搜索工具)专业版值得购买吗?
说到经典的国货软件,有一款 Win 软件是一定绕不过去的。它就是知名的本地文件搜索工具 Listary! 便捷的文件搜索窗口;快捷操作的体验;与系统更匹配的外观设计;更智能的排序和更可靠的索引。 便捷的文件搜索窗口 紧凑…...
面试突击指南:Java基础面试题2
面向对象和集合 1. 面向对象和面向过程的区别 面向过程:面向过程的编程方式是分析解决问题的步骤,然后用函数把这些步骤一步一步地实现,并在使用的时候逐个调用。这种方式性能较高,因此在单片机和嵌入式开发中经常采用面向过程开发。 面向对象:面向对象的编程方式是把问…...
MySQL快速安装(mysql8.0.30区别之前yum安装)
目录 一.初始化环境并解压 二.创建程序用户管理 三.修改mysql目录和配置文件的权限 四.修改配置文件 五.设置环境变量,申明/宣告mysql命令便于系统识别 六.初始化数据库 七.设置系统识别,进行操作 八.初始化数据库密码 九.用户并设置密码 十.赋…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态
前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…...
stm32wle5 lpuart DMA数据不接收
配置波特率9600时,需要使用外部低速晶振...
CTF show 数学不及格
拿到题目先查一下壳,看一下信息 发现是一个ELF文件,64位的 用IDA Pro 64 打开这个文件 然后点击F5进行伪代码转换 可以看到有五个if判断,第一个argc ! 5这个判断并没有起太大作用,主要是下面四个if判断 根据题目…...
VSCode 使用CMake 构建 Qt 5 窗口程序
首先,目录结构如下图: 运行效果: cmake -B build cmake --build build 运行: windeployqt.exe F:\testQt5\build\Debug\app.exe main.cpp #include "mainwindow.h"#include <QAppli...
