Vuejs 2: debounce not working on a watch option
Another variation to @Bert's answer is to build the watcher's function in created()
,
// SO: Vuejs 2: debounce not working on a watch optionconsole.clear()Vue.component("debounce",{ props : { debounce : { type : Number, default : 500 } }, template:` <div> <input type="text" v-model="term"> </div> `, data(){ return { term: "", debounceFn: null } }, created() { this.debounceFn = _.debounce( () => { console.log('Debounced term: ' + this.term); }, this.debounce) }, watch : { term : function () { this.debounceFn(); } },})new Vue({ el: "#app"})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script><div id="app"> <debounce :debounce="2000"></debounce></div>
Example on CodePen
The primary issue here is using this.debounce
as the interval when defining your debounced function. At the time _.debounce(...)
is run (when the component is being compiled) the function is not yet attached to the Vue, so this
is not the Vue and this.debounce
will be undefined. That being the case, you will need to define the watch after the component instance has been created. Vue gives you the ability to do that using $watch.
I would recommend you add it in the created lifecycle handler.
created(){ this.unwatch = this.$watch('term', _.debounce((newVal) => { console.log('Debounced term: ' + this.term); }, this.debounce))},beforeDestroy(){ this.unwatch()}
Note above that the code also calls unwatch
which before the component is destroyed. This is typically handled for you by Vue, but because the code is adding the watch manually, the code also needs to manage removing the watch. Of course, you will need to add unwatch
as a data property.
Here is a working example.
console.clear()Vue.component("debounce",{ props : { debounce : { type : Number, default : 500 } }, template:` <input type="text" v-model="term"> `, data(){ return { unwatch: null, term: "" } }, created(){ this.unwatch = this.$watch('term', _.debounce((newVal) => { console.log('Debounced term: ' + this.term); }, this.debounce)) }, beforeDestroy(){ this.unwatch() }})new Vue({ el: "#app"})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script><script src="https://unpkg.com/vue@2.4.2"></script><div id="app"> <debounce :debounce="250"></debounce></div>
new Vue({ el: '#term', data: function() { return { term: 'Term', debounce: 1000 } }, watch: { term : _.debounce(function () { console.log('Debounced term: ' + this.term); }, this.debounce) }})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.js"></script><div id="term"> <input v-model="term"></div>