Vue监听值改变事件与函数去抖

在做监听事件时,往往会由于事件频繁被触发,因而频繁执行一些操作,导致页面卡顿甚至浏览器崩溃。

1. 背景

  在做搜索功能时,常常会有这样的需求:用户输入字符,程序向后台请求数据,从而在用户的输入框下拉菜单中提示推荐词。

  但这么设计的话会有一些问题:
  ● 用户每输入一个字符,就发送一次请求,极大地增加了服务器的负担。
  ● 有可能会发生请求返回顺序问题,即当输入速度很快时,连续发请求,服务器可能先返回后面的请求结果,再返回输入第一个字符时的请求结果。这显然不是我们想要的。

2. 思路

  ● vue中实时监听input值的变化,停止输入一定时间(可以是300ms)后才去请求,而不是时时请求数据。
    ৹ 自然而然想到了定时器:在指定间隔内没有输入时,才会执行函数;如果停止输入但是在指定间隔内又输入,会重新触发计时。
    ৹ 这就是 函数去抖(debounce)。

  ● 解决异步请求可能发生先请求后返回问题,导致结果列表不是预料展示的效果。
    ৹ 在请求里做判断,当请求返回结果时,判断请求的携带的参数当前输入框的值是否相等,从而进行相关操作。

3. 代码实现 - 函数去抖

my-component.vue

<template>
  <div class="my-component">
    <input ref="searchKeyword" v-model="keyword" type="text" placeholder="搜索关键字" maxlength="20"/>
  </div>
</template>

<script>
export default {
  name: 'MyComponent',
  data() {
    return {
      keyword: '',
      timeout: null,
    }
  },
  watch: {
    keyword(newVal, oldVal) {
      // 防止input连续输入时,频繁发请求
      clearTimeout(this.timeout)
      this.timeout = setTimeout(() => {
        // 异步请求
        this.getMembersData(newVal);
      }, 300);
    }
  }
}
</script>

4. 代码实现 - 返回顺序判断

  上面的代码中,我们通过 300ms 的延迟来实现函数去抖,但服务器还是可能存在先请求后返回,后请求先返回的问题

  为了避免这种返回顺序的问题,我们可以在请求里做判断。当请求返回结果时,判断请求的参数keyword 和当前输入框的值 this.keyword 是否相等,如果相等才进行下一步操作。

// 关键代码:避免先请求后返回问题,确保返回的结果是以当前输入的值为参数的
if (this.keyword === keyword) {
  // 执行一些操作
}

5. 一些文章

  《函数去抖(debounce)和函数节流(throttle)》
  《Vue官网:带有 debounce 的 v-model》


  目录