当前位置: 首页 > news >正文

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 例子 先看一个代码例子&#xff1a; <template>{{ dataList }} </template><script setup lang"ts"> import { ref, watch } from "vue";const dataList ref([]); const props defineProps([&q…...

【LLM 评估】GLUE benchmark:NLU 的多任务 benchmark

论文&#xff1a;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&#xff08;Corpus of Linguistic Accep…...

Go线程调度器

基本结构 字段gcwaiting、stopwait和stopnoted都是串行运行时任务执行前后的辅助协调手段 gcwaiting字段的值用于表示是否需要停止调度 在停止调度前&#xff0c;该值会被设置为1在恢复调度之前&#xff0c;该值会被设置为0这样做的作用是&#xff0c;一些调度任务在执行时只…...

使用 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 …...

若依-前后端分离项目学习

★★★★★省流 直接看第一集和最后一集★★★★★ 第一天&#xff08;6.24&#xff09; 具体参考视频 b站 楠哥教你学Java 【【开源项目学习】若依前后端分离版&#xff0c;通俗易懂&#xff0c;快速上手】 https://www.bilibili.com/video/BV1HT4y1d7oA/?shar…...

使用adb shell getprop命令获取Android设备的属性

常用属性获取&#xff1a; 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&#xff08;Linux、Nginx、MySQL、PHP&#xff09;环境。 系统环境 系统平台&#xff1a;CentOS release 6.5 安装前准备 在安装LNMP之前&#xff0c;您需要安装一些编译器和依赖包。 必备编译器和工具 #安装gcc、gcc-c编译器&#…...

[stm32]温湿度采集与OLED显示

一、I2C总线协议 I2C&#xff08;Inter-integrated circuit &#xff09;是一种允许从不同的芯片或电路与不同的主芯片通信的协议。它仅用于短距离通信&#xff0c;是一种用于两个或多个设备之间进行数据传输的串行总线技术&#xff0c;它可以让你在微处理器、传感器、存储器、…...

大模型知识库的使用

大模型知识库的使用通常涉及以下几个方面&#xff0c;使用大模型知识库可以提高信息检索的准确性和效率&#xff0c;促进知识的传播和应用。同时&#xff0c;也需要关注知识库的质量和更新&#xff0c;以确保提供的知识是准确和可靠的。北京木奇移动技术有限公司&#xff0c;专…...

Docker - Oracle Database 23ai Free

博文目录 文章目录 说明命令NavicatSYSTEMPDBADMIN 扩展公共用户本地用户 说明 Oracle 官方镜像仓库 Database 23ai Free | Oracle Docker 官方没有提供 Oracle Database 相关镜像, 但是 Oracle 官方镜像仓库有提供, 打开上面的链接, 选择 Database, 选择合适的版本, 如 enter…...

spring常用方法

1. 读取配置文件信息 方式一&#xff1a; // 获取文件路径 String fileName "application.yaml"; String filePath this.getClass().getClassLoader().getResource(fileName).getPath();BufferedReader bufferedReader new BufferedReader(new FileReader(path)…...

虚拟机能装在移动硬盘里吗安全吗 PD虚拟机迁移到移动硬盘的方法

虚拟机技术的迅速发展为用户提供了更为灵活的跨系统办公方案。许多用户希望在不同的电脑设备上运行相同的虚拟机&#xff0c;同时带来的也有一个问题&#xff1a;虚拟机能否装在移动硬盘里&#xff1f;针对用户的疑问&#xff0c;接下来给大家介绍虚拟机能装在移动硬盘里吗&…...

刷算法Leetcode---7(二叉树篇)(前中后序遍历)

前言 本文是跟着代码随想录的栈与队列顺序进行刷题并编写的 代码随想录 好久没刷算法了&#xff0c;最近又开始继续刷&#xff0c;果然还是要坚持。 二叉树的题目比之前多了好多&#xff0c;就多分几次写啦~ 这是力扣刷算法的其他文章链接&#xff1a;刷算法Leetcode文章汇总 …...

AliyunOS安装Node.js

方法1&#xff1a;dnf软件包安装工具自动安装 最方便的安装方式是通过系统的dnf工具&#xff0c;我测试使用的AliyunOS的版本是Alibaba Cloud Linux 3.2104&#xff0c;具体流程如下&#xff1a; dnf module list nodejs #列出服务器中可以使用的所有nodejs版本确定下来希望安…...

three.js - MeshPhongMaterial材质(实现玻璃水晶球效果)

1、概念 phong网格材质&#xff1a;Mesh - Phong - Material 一种用于具有镜面高光的光泽表面的材质。 它可以模拟&#xff0c;具有镜面高光的光泽表面&#xff0c;提供镜面反射效果。 MeshPhongMaterial&#xff1a; MeshPhongMaterial是一种基于Phong光照模型的材质&#…...

笔记本电脑安装CentOS

正文共&#xff1a;1234 字 24 图&#xff0c;预估阅读时间&#xff1a;2 分钟 前面我们对VPP进行了多次介绍&#xff08;羡慕&#xff01;大佬的VPP能达到180G性能&#xff0c;而我的却只有13.5G&#xff09;&#xff0c;可以发现他的很多优点&#xff0c;但是我们也可以发现它…...

ssh转发功能入门

端口转发概述 端口转发&#xff0c;能够将其他TCP端口的网络数据通过SSH链路转发&#xff0c;并且提供了ssh的加密和解密的服务。 ssh端口转发有如下这些优点&#xff1a; 提供了ssh的加密传输&#xff0c;利于安全能够突破防火墙限制 目前ssh端口转发有如下几种方式&#x…...

Listary(Windows 文件搜索工具)专业版值得购买吗?

说到经典的国货软件&#xff0c;有一款 Win 软件是一定绕不过去的。它就是知名的本地文件搜索工具 Listary&#xff01; 便捷的文件搜索窗口&#xff1b;快捷操作的体验&#xff1b;与系统更匹配的外观设计&#xff1b;更智能的排序和更可靠的索引。 便捷的文件搜索窗口 紧凑…...

面试突击指南:Java基础面试题2

面向对象和集合 1. 面向对象和面向过程的区别 面向过程:面向过程的编程方式是分析解决问题的步骤,然后用函数把这些步骤一步一步地实现,并在使用的时候逐个调用。这种方式性能较高,因此在单片机和嵌入式开发中经常采用面向过程开发。 面向对象:面向对象的编程方式是把问…...

MySQL快速安装(mysql8.0.30区别之前yum安装)

目录 一.初始化环境并解压 二.创建程序用户管理 三.修改mysql目录和配置文件的权限 四.修改配置文件 五.设置环境变量&#xff0c;申明/宣告mysql命令便于系统识别 六.初始化数据库 七.设置系统识别&#xff0c;进行操作 八.初始化数据库密码 九.用户并设置密码 十.赋…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...