Search code examples
javascriptunderscore.jsvue.jslodash

Are Vue.js and debounce (lodash/underscore) compatible?


Following an answer to my question on debouncing I am wondering if vue.js and lodash/underscore are compatible for this functionality. The code in the answer

var app = new Vue({
  el: '#root',
  data: {
    message: ''
  },
  methods: {
    len: _.debounce(
      function() {
        return this.message.length
      }, 
      150 // time
    )
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.6/vue.js"></script>
<script src="https://unpkg.com/[email protected]"></script> <!-- undescore import -->
<div id="root">
  <input v-model="message">Length: <span>{{ len() }}</span>
</div>

indeed holds on the execution of my function when there is continuous input, but when it is finally executed after some inactivity, the input for function() seems to be wrong.

A practical example after starting the code above:

  1. quick sequence of characters, then no activity:

enter image description here

  1. One extra character (b) added, and no activity -- the length is updated (but wrongly, see below)

enter image description here

  1. Erase all the characters with Backspace in a quick sequence:

enter image description here

  1. Add one character:

enter image description here

It looks like the function is ran on the last but one value of message.

Could it be that _.debounce handles the vue.js data before it is actually updated with the <input> value?

Notes:

  • tested with both lodash and underscore, with the same results (for both debounceand throttle functions).
  • I also tested it on JSFiddle in case there would be some interference with the SO snippet

Solution

  • Here's an improved version of @saurabh's version.

    var app = new Vue({
      el: '#root',
      data: {
        message: '',
        messageLen: 0
      },
      methods: {
        updateLen: _.debounce(
          function() {
            this.messageLen = this.message.length
          }, 300)        
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.6/vue.js"></script>
    <script src="https://unpkg.com/[email protected]"></script> <!-- undescore import -->
    <div id="root">
      <input v-model="message" v-on:keyup="updateLen">Length: <span>{{ messageLen }}</span>
    
    </div>