Vue3 watchEffect 一个自动依赖收集的注意问题

本文讲述了作者在开发中遇到的一个请求重复问题,通过分析发现是由于响应式变量在watchEffect中的频繁修改导致的。通过限制变量的改变条件并使用深拷贝,成功解决了这个问题。
摘要由CSDN通过智能技术生成

在写代码的时候突然发现一个请求重复请求了31次。这给我整不会了。

首先排查bug的可能原因:

  1. 认为其中的一些依赖的变量,在某些外部地方进行频繁的修改(因为Vue3 Ref响应式导出传递这个的可能行我认为是最大的, 这个方向帮我优化了一些其他问题,但是并不是造成这个bug的原因)。
  2. 依赖收集中的变量,它本身的属性被多次赋值。(后续思考了一下vue2源码响应式中对这个问题是由解决的,vue3不可能会出现错误。这个是错误的方向)
  3. 依赖收集的多个变量在本次watch中,是不是一直在被赋值。

最后发现,在这个watchEffect中有2个响应式变量每次都在修改。然后每次执行这个watchEffect的时候依赖收集到这2个变量上面。就会执行2次函数。然后这样就会出现重复执行bug。

贴一下这个bug的代码和优化后的代码

// 优化后的代码
// 依赖收集的响应式变量有companyList、companyBillCategory、companyAllBillCategory
// 在这份代码中限制了companyBillCategory、companyAllBillCategory的改变条件,让触发重复的情况减少
watchEffect(async () => {
    if (companyList.value.length === 0) {
      return;
    }
    // 这里因为获取了对象的数据所以进行了依赖收集

    // 这是之前的问题代码。因为这里直接使用响应式变量的数据,所以后续companyBillCategoryTemp[item.companyId]每一次的赋值都是对响应式变量的修改触发watchEffect收集的函数导致这个函数会一直执行下去。billCategoryListTemp[it.id]这个也是同理。
    // let companyBillCategoryTemp = companyBillCategory.value;
    // let billCategoryListTemp = companyAllBillCategory.value;

    //这里如果使用了结构,每次修改这个对象的一级属性的时候就不算是修改响应式变量了,就不会触发watchEffect
    let companyBillCategoryTemp = {...companyBillCategory.value};
    let billCategoryListTemp = {...companyAllBillCategory.value};
    // 遍历用户公司列表 然后查看是否有新公司 然后获取公司的账单类型写入
    for (let i = 0; i < companyList.value.length; i++) {
      let item = companyList.value[i];
      if (companyBillCategory.value[item.companyId]) {
        continue;
      }
// 依赖收集到这里就停止了,因为异步会让依赖收集停止
      let billCategoryList = await getCompanyBillCategory(localStorage['id'], item.companyId);
      companyBillCategoryTemp[item.companyId] = billCategoryList.categories.map(it => {
        // 更新公司类型的时候同时更新全部类型的数据
        let res = {
          id: it.id,
          name: it.name,
          isOut: it.is_out
        };
        billCategoryListTemp[it.id] = res;
        return res
      })
    }
    if(Object.keys(companyBillCategoryTemp).length !== Object.keys(companyBillCategory.value).length) {
      companyBillCategory.value = companyBillCategoryTemp;
    }
    if(Object.keys(billCategoryListTemp).length !== Object.keys(companyAllBillCategory.value).length) {
      companyAllBillCategory.value = billCategoryListTemp;
    }
  })

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值