<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逻辑很复杂同步计算出新list const newList = getListFromDisabledList(dataList.value); dataList.value = newList; }, { deep: true } ); watch( () => props.type, () => { // 根据type逻辑很复杂同步计算出新list const newList = getListFromType(dataList.value); dataList.value = newList; } ); watch( () => props.id, () => { // 从服务端获取dataList fetchDataList(); }, { immediate: true } ); </script>上面这个例子在template中渲染了dataList,当props.id更新时和初始化时从服务端异步获取dataList。当props.disableList和props.type更新时,同步的计算出新的dataList。
watch( () => props.xxx, () => { // 加上产品最新的业务逻辑 const newList = getListFromXxx(dataList.value); dataList.value = newList; } );迭代几次业务后这个vue文件里面就变成了一堆watch,屎山代码就是这样形成的。当然不排除有的情况是故意这样写的,为的就是稳定自己在团队里面的地位,因为离开了你这坨代码没人敢动。
<template> {{ renderDataList }} </template> <script setup lang="ts"> import { ref, computed, watch } from "vue"; const props = defineProps(["disableList", "type", "id"]); const dataList = ref([]); //堆代码 duidaima.com const renderDataList = computed(() => { // 根据disableList计算出list const newDataList = getListFromDisabledList(dataList.value); // 根据type计算出list return getListFromType(newDataList); }); watch( () => props.id, () => { // 从服务端获取dataList fetchDataList(); }, { immediate: true, } ); </script>我们在template中渲染的不再是dataList变量,而是renderDataList。renderDataList是一个computed,在这个computed中包含了所有dataList同步相关的逻辑。代码逻辑流程图是这样的:
const renderDataList = computed(() => { // 加上产品最新的业务逻辑 const xxxList = getListFromXxx(dataList.value); // 根据disableList计算出list const newDataList = getListFromDisabledList(xxxList); // 根据type计算出list return getListFromType(newDataList); });
这篇文章介绍了watch主要分为两种使用场景,一种是当watch的值改变后需要同步更新渲染的dataList,另外一种是当watch的值改变后需要异步从服务端获取要渲染的dataList。如果不管同步还是异步都一股脑的将所有代码都写在watch中,那么后续接手的维护者要梳理dataList相关的逻辑就会非常痛苦。因为到处都是watch在更新dataList的值,完全不知道应该在哪个watch中去加上最新的业务逻辑,这种时候我们一般就会再新加一个watch然后在新的watch中去实现最新的业务逻辑,时间久了代码中就变成了一堆watch,维护性就变得越来越差。
我们给出的优化方案是将那些同步更新dataList的watch代码全部摞到一个名为renderDataList的computed,后续维护者只需要判断新的业务如果是同步更新dataList,那么就将新的业务逻辑写在computed中。如果是要异步更新dataList,那么就将新的业务逻辑写在watch中。