工具函数之节流函数

起因

场景是需要对一个Vue的搜索组件进行优化。输入框中进行了数据的双向绑定,由于在 created 钩子函数中监听了数据的变化,使得每次更改数据都会发送请求,最终导致性能和流量的浪费。

部分代码

<template>
  <div class="search-box">
    <input class="box" v-model="query">
  </div>
</template>

<script>
export default {
  data() {
    return {
      query: ''
    }
  },

  created() {
    this.$watch('query', (newQuery) => {
      this.$emit('query', newQuery) // 向外部派发query事件
    })
  }
}
</script>

解决方案

一种解决方案是写一个节流函数来避免频繁的输入更改导致的数据请求。

export function debounce(func, delay) {
  let timer
  return function (...args) {
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      func.apply(this, args)
    }, delay)
  }
}

debounce 函数接收两个参数: 需要执行的函数和延时的时间。返回一个匿名函数,该函数会先判断是否存在 timer,有则清除掉,否则就对 func 延迟执行,这样如果过快的调用debounce 函数,则每次 timer 都会被清除直到最后一次延迟执行 func。

修改之前的代码为

created() {
    this.$watch('query', debounce((newQuery) => {
      this.$emit('query', newQuery)
    },200))
  }

这样为监听的回调函数加上一层 debounce ,可以使每次输入间隔超过200ms后才会向父级组件派发 query 事件。