How to implement debounce in Vue2? How to implement debounce in Vue2? vue.js vue.js

How to implement debounce in Vue2?


I am using debounce NPM package and implemented like this:

<input @input="debounceInput">
methods: {    debounceInput: debounce(function (e) {      this.$store.dispatch('updateInput', e.target.value)    }, config.debouncers.default)}

Using lodash and the example in the question, the implementation looks like this:

<input v-on:input="debounceInput">
methods: {  debounceInput: _.debounce(function (e) {    this.filterKey = e.target.value;  }, 500)}


Option 1: Re-usable, no deps

- Recommended if needed more than once in your project

/helpers.js

export function debounce (fn, delay) {  var timeoutID = null  return function () {    clearTimeout(timeoutID)    var args = arguments    var that = this    timeoutID = setTimeout(function () {      fn.apply(that, args)    }, delay)  }}

/Component.vue

<script>  import {debounce} from './helpers'  export default {    data () {      return {        input: '',        debouncedInput: ''      }    },    watch: {      input: debounce(function (newVal) {        this.debouncedInput = newVal      }, 500)    }  }</script>

Codepen


Option 2: In-component, also no deps

- Recommended if using once or in small project

/Component.vue

<template>    <input type="text" v-model="input" /></template><script>  export default {    data: {        timeout: null,        debouncedInput: ''    },    computed: {     input: {        get() {          return this.debouncedInput        },        set(val) {          if (this.timeout) clearTimeout(this.timeout)          this.timeout = setTimeout(() => {            this.debouncedInput = val          }, 300)        }      }    }  }</script>

Codepen


Assigning debounce in methods can be trouble. So instead of this:

// Badmethods: {  foo: _.debounce(function(){}, 1000)}

You may try:

// Goodcreated () {  this.foo = _.debounce(function(){}, 1000);}

It becomes an issue if you have multiple instances of a component - similar to the way data should be a function that returns an object. Each instance needs its own debounce function if they are supposed to act independently.

Here's an example of the problem:

Vue.component('counter', {  template: '<div>{{ i }}</div>',  data: function(){    return { i: 0 };  },  methods: {    // DON'T DO THIS    increment: _.debounce(function(){      this.i += 1;    }, 1000)  }});new Vue({  el: '#app',  mounted () {    this.$refs.counter1.increment();    this.$refs.counter2.increment();  }});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script><div id="app">  <div>Both should change from 0 to 1:</div>  <counter ref="counter1"></counter>  <counter ref="counter2"></counter></div>