简体   繁体   中英

How to use debounce on `keyup` with Vue.js

I am trying to catch the user started typing, and stopped typing using the debounce function. I tried Lodash and Underscore.js .

On my textArea
                               v-on:keyup="handler($event)"
handler: function(e) {
             this.e = e
             if(this.canPublish) {
                 this.setCanNotPublish()
                 this.doStuff()
             }

             var debounceFunction = _.debounce(this.doneTyping(), 5000)
             debounceFunction(e)

         },

I am getting really frustrated about this. In pure JavaScript I made the test work. But with Vue.js where it uses v-on events, data, methods...etc., I am not able to make it work.

Method doneTyping

doneTyping: function () {
                console.log('done typing....')
            }

}

Method doStuff

doStuff: function () {
             console.log('started typing....')
         }

The intended behaviour is: first the user started typing in the textArea, and it starts the doStuff. And if the user keeps typing in a period shorter than 5 seconds, it will not trigger doStuff again because canPublish is a boolean. Next the user stops typing and then the debounce func is done, and doneTyping fires.

Here's how to debounce your method.

doneTyping: _.debounce(function (e) {
    console.log('done typing....')
}, 5000)

Then you use it like

handler: function(e) {
    this.e = e
    if(this.canPublish){
        this.setCanNotPublish()
        this.doStuff()
    }

    this.doneTyping() // function is debounced
},

I would do with this two debounced functions, one for started typing which triggers on the leading edge, and one for stopped typing which triggers on the trailing edge.

 new Vue({ el: '#app', created() { this.startedTyping = _.debounce(this.startedTyping, 5000, { leading: true, trailing: false, }) this.stoppedTyping = _.debounce(this.stoppedTyping, 5000, { leading: false, trailing: true, }) }, methods: { handleKeydown() { // This triggers on the leading edge this.startedTyping() // This triggers on the trailing edge (after 5s) this.stoppedTyping() }, startedTyping() { console.log('started typing') }, stoppedTyping() { console.log('stopped typing') }, }, })
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.19/lodash.min.js"></script> <div id="app"> <textarea @keydown="handleKeydown"></textarea> </div>

Your code is wrong because you are creating a new debounced function every time the handler is called. You need to have only one debounced function instance that you call each time. It's best to create the debounced function in the created hook.

I often see code like this:

methods: {
  myDebouncedFunc: _.debounce(function () {
    // Do stuff
  }, 1000)
}

This is technically not wrong, but you may not realize that the debounced function will be shared across all instances of that component, which may not be what you want. It's usually best to create the debounced function in the created hook so that each instance of the component gets its own independent debouncing tracking.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM