乐趣区

Vuejs页面中有多个input搜索框如何实现防抖操作使用debounce的正确姿势

原文由熊孩子发表在 Bloghome 博客

debounce 简介

debounce 是 lodash 工具库中的一个非常好用的函数。在实现搜索框对输入进行动态查询的时候,我们需要防止前端频繁的发送查询请求给后端,这个时候就需要用到 debounce,它可以设置一个时间间隔,比如 300ms,忽略 300 毫秒内的输入变化。debounce 的详细介绍可以参考这篇文章。

debounce 的高级用法

博主的页面中有 3 个搜索框,每个搜索框都需要动态响应用户的输入到后台去查询匹配的文章,如下图:

在 Vue.js 中如何实现多搜索框的 debounce 绑定,下面博主就带大家一起来看一下:

1. 监听输入变量

上图,可以看到我有 3 个输入框,每个输入框都需要设置一个变量来保存用户的输入:

    data () {
      return {
        // 可用的文章列表
        columnItems: [],
        // 是否正在加载
        isLoading: [false, false, false],
        // 选择框搜索输入的值
        searchColumn1: '',
        searchColumn2: '',
        searchColumn3: ''
      }
    },

接下来,我们把输入变量绑定到输入框上面。博主这里使用的是 vuetify 的 combobox,如果使用 html 原生的 input 框或者其他框架的 input 元素,此处请稍作修改:

        <label> 推荐专栏 1 </label>
        <v-combobox
          :items="columnItems"
          :loading="isLoading[0]"
          :search-input.sync="searchColumn1"
          ...
        >
        ...
        </v-combobox>
        <label> 推荐专栏 2 </label>
        <v-combobox
          :items="columnItems"
          :loading="isLoading[1]"
          :search-input.sync="searchColumn2"
          ...
        >
        ...
        </v-combobox>
        <label> 推荐专栏 3 </label>
        <v-combobox
          :items="columnItems"
          :loading="isLoading[2]"
          :search-input.sync="searchColumn3"
          ...
        >
        ...
        </v-combobox>

然后,我还需要监听这几个变量,如果发生改变则调用 ajax 进行后台查询:

    watch: {searchColumn1 (val) {this.getColumns(val, 0)
      },
      searchColumn2 (val) {this.getColumns(val, 1)
      },
      searchColumn3 (val) {this.getColumns(val, 2)
      }
    },
    ...
    methods: {getColumns: function (searchValue, index) {
        // Items have already been requested
        if (this.isLoading[index]) return
        this.isLoading[index] = true

        let vm = this
        let options = {page: 1}

        if (searchValue) {options.title = searchValue.trim()
        } else {vm.columnItems = []
          vm.isLoading[index] = false
          return
        }

        // console.log(options)
        vm.$store.dispatch('getAllColumns', options).then(function (columns) {if (columns && columns.length) {vm.columnItems = columns}
          vm.isLoading[index] = false
        })
      }
    }

 

2. 添加 debounce 绑定

到目前为止,我们都还没有添加 debounce,上面的逻辑也完全走的通,但是运行后你会发现输入操作运行的不流畅,如果打开 dev-tools 查看后台调用,你会发现用户输入后出发了一长串的 ajax 调用。因此我们引入 debounce。此处,我们只需把含有 ajax 调用的函数提交给 debounce,告诉它对 getColumns() 函数进行防抖操作。而在何处调用 debounce 则是非常有讲究的,错误的引入位置会使得 debounce 不起作用。请记住,debounce 需要在 created() 钩子中引入。

    import _ from 'lodash'
    ...
    created: function () {this.getColumns = _.debounce(this.getColumns, 500)
    },

最后,博主想抛出一个小问题:“为什么一定要在 created() 钩子中调用 debounce 呢,mounted() 或者其他的地方为什么不可以呢?”,请知道的同学留言或者发评论给我吧!
 

参考资料

  • How to delay watcher method call on an input field

 

更多精选文章

  • 简明 JavaScript 函数式编程
  • 重磅!TypeScript 3.7 RC 发布,备受瞩目的 Optional Chaining 来了
  • Vue 3 最值得期待的五项重大更新
  • Headless Chrome – 在 SPA(Vue/React/Angular) 项目中使用 Puppeteer 实现 SEO
  • ECMAScript6(ES6) 小结
退出移动版