Vue2中watch监听函数添加防抖

760 阅读2分钟

背景

最近接到测试反馈:新增加的一个功能页面,每次页面刷新后第一个调用的时候会出现重复的网络请求被调用了两遍的情况,该功能是通过父组件传递过来的参数来决定加载的时机。也就是说父组件传递给子组件的时候,子组件在监听父组件传递过来的参数的时候,竟然执行了两遍。

代码排查

通过跟踪调试代码发现,父组件传递给子组件参数,子组件监听到父组件传递过来的参数的时候,直接走了两遍的代码,错误的伪代码如下:

props: {
  meidcalObj: {
    type: Object,
    default: () => {}
  }
},
watch: {
  meidcalObj: {
    handler() {
      // 代码逻辑
    },
    deep: true,
    immediate: true
  }
}

于是我搜索了下在什么情况下 watch监听父组件传递过来的子组件参数会执行两遍,得到的答案是这样的:

image.png

解决方案

因为该功能是提供给公司其他产品提供调用的组件,因此实在无法得知其他产品在调用的时候是怎么传递参数的,因此我想到了一种方式解决此问题,那就是通过给监听函数添加防抖,进而解决初次加载页面功能模块加载两次的问题,解决方案代码如下:

watch: {
  meidcalObj: {
    handler() {
      // 代码逻辑
    },
    deep: true,
    immediate: true
  }
},
mounted() {
  this.meidcalObjChange = this.debounce(this.meidcalObjChange, 300)
},
methods: {
  // 防抖函数
  debounce(fn, delay) {
    let timer;
    return function() {
      timer && clearTimeout(timer)
      timer = setTimeout(() => {
        fn.apply(this, arguments)
      }, delay)
    }
  },
  // 此函数就是监听函数的逻辑,将监听函数的逻辑抽取成一个方法
  meidcalObjChange() {
      // 代码逻辑
  }
}

这样就完美解决了调用两次的问题

总结

其实我觉得遇到这样的问题,解决思路肯定不是这样的。应该是去找到导致问题出现的根本原因,然后从根本上去解决,而不是依据问题的现象去解决这样的问题。

本人技术水平有限,欢迎各位大佬讨论指正不足之处