首页 > 其他分享 >Vue3中Watch的同步和异步

Vue3中Watch的同步和异步

时间:2024-10-10 11:52:35浏览次数:14  
标签:异步 逻辑 const dataList watch 代码 props Watch Vue3

在 Vue 3 中,watch 是一个强大的工具,适合监视响应式数据的变化并处理副作用逻辑。最近在做CodeReview的时候,发现了一些对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,
  () => {
    // 基于disableList的逻辑非常复杂,它同步计算一个新列表
    const newList = getListFromDisabledList(dataList.value);
    dataList.value = newList;
  },
  { deep: true }
);
watch(
  () => props.type,
  () => {
    // 基于类型的逻辑非常复杂,同步计算新列表
    const newList = getListFromType(dataList.value);
    dataList.value = newList;
  }
);
watch(
  () => props.id,
  () => {
    // 从数据库拉取数据
    fetchDataList();
  },
  { immediate: true }
);
</script>

在这个例子中,dataList 在模板中渲染。更新 props.id 和初始化时,会异步从服务器获取 dataList。

更新 props.disableList 和 props.type 时,会同步计算新的 dataList。

代码逻辑流程图如下:

乍一看,上面的代码可能没什么问题,但当不熟悉这方面的新同事接手时,问题就来了。

通常,在接手一个我们并不熟悉的业务领域时,我们需要找到一个起点。对于前端来说,这个起点肯定是浏览器中的渲染页面。从模版中我们可以知道 dataList 变量是核心所在,它有多个来源。

首先,服务器通过对 props.id 的监视进行异步更新。然后,通过对 props.disableList 和 props.type 的监视同步更新。

此时,不熟悉业务的同事如果收到要更新检索 dataList 逻辑的产品需求,就必须首先熟悉其多个来源背后的逻辑。

那么就要去看getListFromDisabledList、getListFromType例复杂的代码,分析清楚应该修改哪块才能满足产品要求。

不过,在实际操作中,当维护别人的代码(尤其是复杂的代码)时,我们一般不喜欢修改现有的代码,而是在上面添加自己的代码。更改他人的复杂代码很可能会引入错误(特别是有一些摸不着头脑的逻辑时),而我们也可能会因此造成生产事故。因此,我们通常的做法是添加另一个监视器,并在那里实现 dataList 的最新业务逻辑:

watch(
  () => props.xxx,
  () => {
    // Add the latest business logic
    const newList = getListFromXxx(dataList.value);
    dataList.value = newList;
  }
);

经过多次迭代后,这个 vue 文件就会变得杂乱无章,其中包含大量的观察语句,从而导致 "意大利面条代码"(Spaghetti Code 是一个编程术语,用于描述结构混乱、难以理解和维护的代码)。又或许这种编码风格可能是为了假装提高自己在团队中的价值,确保自己在团队中的地位,没有其他人敢碰这个复杂的代码。哈哈。

破局

上面这个例子,实际上是由于dataList的变更源过多引起的,而且里面还包含同步和异步两种。我们可以增加computed,把同步的变更整合到computed里,只保留异步的变更:

<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(() => {
  const newDataList = getListFromDisabledList(dataList.value);
  return getListFromType(newDataList);
});

watch(
  () => props.id,
  () => {
    fetchDataList();
  },
  {
    immediate: true,
  }
);
</script>

我们不再渲染 dataList 变量,而是渲染 renderDataList。代码逻辑流程图如下:

当新的团队成员收到迭代 dataList 相关业务的产品需求时,由于我们的整个业务逻辑现在已经变成了一个线性序列,因此新的团队成员可以快速理清业务逻辑。

然后,根据产品的要求,他们可以决定是修改同步逻辑还是修改异步逻辑。以下是修改同步逻辑的演示:

const renderDataList = computed(() => {
  // 添加最新的处理逻辑
  const xxxList = getListFromXxx(dataList.value);
  const newDataList = getListFromDisabledList(xxxList);
  return getListFromType(newDataList);
});

总结

我们应该更多地使用 computed 来处理同步逻辑,将异步逻辑保留在 watch 中的方法。 computed 本身具备缓存特性,通过使用computed,我们可以减少状态的数量,因为computed是计算属性,是一个中间结果,是因变量不是自变量。

  • 滥用 watch 会导致代码难以维护: 当 watch 被用于处理多个复杂的同步和异步更新时,会导致代码变得杂乱无章,给维护和理解业务逻辑带来困难。

  • computed 和 watch 的适当使用可以提高代码质量: 将同步逻辑放入 computed 中,这样可以将业务逻辑线性化,使得代码更加清晰。同时,将异步逻辑保留在 watch 中,可以更好地区分和管理不同类型的更新。

  • 优化后的代码结构有助于新成员快速上手: 通过将同步逻辑集中在 computed 中,新成员可以快速定位需要修改的业务逻辑,提高开发效率和代码的可维护性。

  • 代码逻辑应该是线性和可追溯的: 代码逻辑应该像一个线程一样,从而使得业务逻辑的流向清晰明了,避免复杂的逻辑分叉和嵌套,这有助于代码的长期维护。

原文:https://juejin.cn/post/7422888182495920166

 

标签:异步,逻辑,const,dataList,watch,代码,props,Watch,Vue3
From: https://blog.csdn.net/gaotlantis/article/details/142766742

相关文章

  • Vue3 封装不定高虚拟列表 hooks
    //useVirtualList.tsimport{ref,onMounted,onBeforeUnmount,watch,nextTick}from"vue";importtype{Ref}from"vue";interfaceConfig{data:Ref<any[]>;//数据源scrollContainer:string;//滚动容器的元素选择器actualHeightC......
  • 异步场景: promise、async函数与await命令介绍
    如果你也对鸿蒙开发感兴趣,加入“Harmony自习室”吧!扫描下方名片,关注公众号,公众号更新更快,同时也有更多学习资料和技术讨论群。在鸿蒙的开发中,我们时常会遇到promise异步场景,有同学反馈说希望提一下。异步开发这部分的内容比较多,我不确定这位朋友具体想讨论是哪些方面,那我从......
  • 从零搭建Cesium+vue3+vite
    介绍在现代前端开发中,Cesium是一个功能强大的WebGL库,广泛应用于3D地球可视化、空间数据展示等领域。结合Vue3的组件化开发模式,我们可以创建一个高效且可维护的3D地图应用。本文将带你一步步搭建一个简单的Cesium+Vue3项目,并且对各个功能模块进行细致划分,帮助你快......
  • 基于Vue3+pinia+vue-router+axios+element-plus等开发的新闻发布管理系统
    新闻发布管理系统是一个基于Vue3+pinia+vue-router+axios+element-plus等开发的系统,主要功能包括:登录模块、注册模块、新闻分类管理模块、新闻管理模块、个人中心模块(包括基本资料、更换头像、重置密码功能)等。代码下载:源码下载基于Vue3开发的新闻发布管理系统,使用的前端......
  • 尚硅谷vue3实战项目--硅谷甄选项目笔记
    硅谷甄选运营平台此次教学课程为硅谷甄选运营平台项目,包含运营平台项目模板从0到1开发,以及数据大屏幕、权限等业务。此次教学课程涉及到技术栈包含:vue3+TypeScript+vue-router+pinia+element-plus+axios+echarts等技术栈。一、vue3组件通信方式通信仓库地址:https://gitee.c......
  • 在Vue3中使用vuex
    官方文档vue3+ts一、安装npminstallvuex@next--save二、创建并引入1.新建store文件夹,在store目录下新建index.jsimport{createStore}from'vuex'exportdefaultcreateStore({state:{},mutations:{},actions:{}modules:{}})2.......
  • vue3中如何实现通用头部?
    在Vue中实现通用头部可以通过以下几种方式:一、使用Vue组件创建头部组件首先,创建一个名为HeaderComponent.vue的Vue组件文件。在这个组件中,可以使用Vue的模板语法来设计头部的结构,例如包含导航栏、品牌标志、搜索框等元素。<template><header><......
  • 【Spring Security OAuth2】- 【使用Spring MVC开发RESTful API】 异步处理rest服务
    作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬学习必须往深处挖,挖的越深,基础越扎实!阶段1、深入多线程阶段2、深入多线程设计模式阶段3、深入juc源码解析阶段4、深入jdk其余源码解析......
  • [Vue] 异步路由组件和非路由组件的区别?
    异步路由组件都知道异步路由组件通过()=>import("./views/Home.vue")导入路由组件。但是它怎么就按需加载资源、代码分割了?不同的代码解析报告非异步路由组件异步路由组件代码分析报告生成代码pnpminstallwebpack-bundle-analyzerfile:[vue.config.js]const{......
  • vue3 pinia 存数据
    pinia是vue2中的vuex,状态管理,可以实现数据共享1、先安装npminstallpinia 2、在main.ts中进行创建和载入3、在src下新建store文件夹定义存的文件  4、在组件中使用 此时控制台会有具体的值。   ......