我在Vue模板中有一个简单的输入框,我想使用debounce或多或少像这样:

<input type="text" v-model="filterKey" debounce="500">

然而,在Vue 2中debounce属性已被弃用。建议只说:“使用v-on:输入+第三方反弹功能”。

如何正确地实现它?

我尝试使用lodash, v-on:input和v-model来实现它,但我想知道是否有可能没有额外的变量。

在模板:

<input type="text" v-on:input="debounceInput" v-model="searchInput">

在脚本:

data: function () {
  return {
    searchInput: '',
    filterKey: ''
  }
},

methods: {
  debounceInput: _.debounce(function () {
    this.filterKey = this.searchInput;
  }, 500)
}

然后在计算道具中使用过滤键。


当前回答

<template>
  <input type="text" v-model="search" @input="debouncedSearch" />
</template>

<script>
import _ from 'lodash';

export default {
  data() {
    return {
      search: '',
    };
  },
  methods: {
    search() {
      // Perform the search here
      console.log(this.search);
    },
  },
  created() {
    this.debouncedSearch = _.debounce(this.search, 1000);
  },
};
</script>

其他回答

在方法中分配debounce可能会很麻烦。所以不要这样:

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

你可以试试:

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

如果您有一个组件的多个实例,这就会成为一个问题——类似于数据应该是一个返回对象的函数。每个实例都需要自己的debounce函数,如果它们被认为是独立的。

这里有一个问题的例子:

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>

如果你正在使用Vue,你也可以使用v.model.lazy而不是debounce,但记住v.model.lazy并不总是有效,因为Vue限制它用于自定义组件。

对于自定义组件,您应该使用:value和@change.native

<b-input:value="data" @change。Native ="data = $event.target. "价值”> < / b-input >

选项1:可重复使用,无deps

-如果在你的项目中需要不止一次,建议使用

/ 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


选项2:组件内,也没有deps

-建议一次性使用或用于小型项目

/ 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

短版本使用箭头函数,默认延迟值

文件:debounce.js in ex: (import debounce from '../../跑龙套/防反跳”)

export default function (callback, delay=300) {
    let timeout = null
    return (...args) => {
        clearTimeout(timeout)
        const context = this
        timeout = setTimeout(() => callback.apply(context, args), delay)
    }
}

2 Mixin选项

文件:debounceMixin.js

export default {
  methods: {
    debounce(func, delay=300) {
      let debounceTimer;
      return function() {
       // console.log("debouncing call..");
        const context = this;
        const args = arguments;
        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(() => func.apply(context, args), delay);
        // console.log("..done");
      };
    }
  }
};

在vueComponent中使用:

<script>
  import debounceMixin from "../mixins/debounceMixin";
  export default {
   mixins: [debounceMixin],
        data() {
            return {
                isUserIdValid: false,
            };
        },
        mounted() {
        this.isUserIdValid = this.debounce(this.checkUserIdValid, 1000);
        },
    methods: {
        isUserIdValid(id){
        // logic
        }
  }
</script>

另一个选项,例子

Vue搜索输入反弹

如果你需要使用lodash的debounce函数来应用动态延迟:

props: {
  delay: String
},

data: () => ({
  search: null
}),

created () {
     this.valueChanged = debounce(function (event) {
      // Here you have access to `this`
      this.makeAPIrequest(event.target.value)
    }.bind(this), this.delay)

},

methods: {
  makeAPIrequest (newVal) {
    // ...
  }
}

模板:

<template>
  //...

   <input type="text" v-model="search" @input="valueChanged" />

  //...
</template>

注意:在上面的例子中,我做了一个搜索输入的例子,它可以用props中提供的自定义延迟调用API