Debounce computed properties/getters in Vue

前端 未结 3 612
名媛妹妹
名媛妹妹 2020-12-11 01:20

I can\'t seem to debounce (lodash) computed properties or vuex getters. The debounced functions always return undefined.

https://jsfiddle.net/guanzo/yqk0jp1j/2/

相关标签:
3条回答
  • 2020-12-11 01:54
    1. Simple
    2. No external dependencies (like _.debounce)
    3. Tailored for Vue
    import Vue from 'vue'
    
    // Thanks to https://github.com/vuejs-tips/v-debounce/blob/master/debounce.js
    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)
      }
    }
    
    function debouncedProperty(delay) {
      let observable = Vue.observable({ value: undefined });
      return {
        get() { return observable.value; },
        set: debounce(function (newValue) { observable.value = newValue; }, delay)
      }
    }
    
    // component
    export default {
      computed: {
        myProperty: debouncedProperty(300),
      },
    }
    
    0 讨论(0)
  • 2020-12-11 01:55

    I don't have any insight as to why the debounce function doesn't work on a computed property. However, an alternative solution is to put the debounce on a function in the methods section and call it via a watch.

    https://jsfiddle.net/vsc4npv3/

    HTML:

    <div id="app">
    <input v-model="text">
    <div>computed: {{ textComputed }} </div>
    <div>debounced: {{ debouncedText }} </div>
    </div>
    

    JavaScript:

    var x = new Vue({
        el:'#app',
      data:{
        text:'',
        debouncedText: ''
      },
      watch: {
        text: function (val) {
            this.debouncer();
        }
      },
      computed:{
        textComputed(){
            return this.text;
        }
      },
      methods: {
        debouncer: _.debounce(function(){
          this.debouncedText = this.text;
        },500)
      }
    
    })
    
    0 讨论(0)
  • 2020-12-11 02:12

    As I mention in my comment, debouncing is an inherently asynchronous operation, and so cannot return a value. Depending on your needs, you might want to debounce on the input side. There will be no difference between the value in text and that in textComputed, but if you v-model="textComputed", the value setting will be debounced.

    If you specifically want a debounced version of a variable, mrogers has given a good solution.

    var x = new Vue({
      el: '#app',
      data: {
        text: 'start'
      },
      computed: {
        textComputed: {
          get() {
            return this.text;
          },
          set: _.debounce(function(newValue) {
            this.text = newValue;
          }, 500)
        }
      }
    })
    <script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
    <div id="app">
      <div>
        Debounced input:
        <input v-model="textComputed">
      </div>
      <div>
        Immediate input:
        <input v-model="text">
      </div>
      <div>computed: {{ textComputed }} </div>
      <div>debounced: {{ text }} </div>
    </div>

    0 讨论(0)
提交回复
热议问题