227 votes

Comment implémenter anti-rebond dans Vue2?

J'ai une simple zone de saisie dans une Vue de modèle et je voudrais profiter de l'anti-rebond plus ou moins comme ceci:

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

Cependant, l' debounce de la propriété a été déprécié en Vue 2. La recommandation est dit que: "l'utilisation v:entrée + 3ème partie de la fonction anti-rebond".

Comment avez-vous correctement les mettre en œuvre?

J'ai essayé de la mettre en œuvre à l'aide de lodash, v:entrée et v-modèle, mais je me demande si c'est possible de le faire sans la variable supplémentaire.

Dans le modèle:

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

Dans le script:

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

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

Le filterkey est ensuite utilisé plus tard, en computed accessoires.

228voto

Primoz Rome Points 1323

J'utilise le paquet debounce NPM et je l'implémente comme ceci:

 <input @input="debounceInput">

methods: {
    debounceInput: debounce(function (e) {
      this.$store.dispatch('updateInput', e.target.value)
    }, config.debouncers.default)
}
 

En utilisant lodash et l'exemple de la question, l'implémentation ressemble à ceci:

 <input v-on:input="debounceInput">

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

105voto

bendytree Points 2684

Attribution d'anti-rebond en methods peut-être des ennuis. Ainsi, au lieu de ceci:

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

Vous pouvez essayer:

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

Il devient un problème si vous avez plusieurs instances d'un composant semblable à la manière data doit être une fonction qui retourne un objet. Chaque instance a besoin de sa propre fonction anti-rebond, si ils sont censés agir de façon indépendante.

Voici un exemple de problème:

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>

12voto

stallingOne Points 1199

J'ai eu le même problème et cela a fonctionné sans plugins .

Puisque <input v-model="xxxx"> est exactement le même que

 <input
   v-bind:value="xxxx"
   v-on:input="xxxx = $event.target.value"
>
 

(la source)

J'ai pensé que je pourrais définir une fonction anti-rebond sur l'attribution de xxxx dans xxxx = $event.target.value

comme ça

 <input
   v-bind:value="xxxx"
   v-on:input="debounceSearch($event.target.value)"
>
 

méthodes:

 debounceSearch(val){
  if(search_timeout) clearTimeout(search_timeout);
  var that=this;
  search_timeout = setTimeout(function() {
    that.xxxx = val; 
  }, 400);
},
 

9voto

bakkelun Points 865

Si vous avez besoin d’une approche très minimaliste à cet égard, j’en ai créé une (initialement fournie par Vuejs-tips pour supporter également IE) qui est disponible ici: https://www.npmjs.com/package/v-debounce

Usage:

 <input v-model.lazy="term" v-debounce="delay" placeholder="Search for something" />
 

Puis dans votre composant:

 <script>
export default {
  name: 'example',
  data () {
    return {
      delay: 1000,
      term: '',
    }
  },
  watch: {
    term () {
      // Do something with search term after it debounced
      console.log(`Search term changed to ${this.term}`)
    }
  },
  directives: {
    debounce
  }
}
</script>
 

7voto

sm4 Points 1317

Veuillez noter que j'ai posté cette réponse avant de la accepté de répondre. Ce n'est pas correct. C'est juste un petit pas en avant à partir de la solution dans le question. J'ai édité les acceptée question afin de montrer à la fois l'auteur de la mise en œuvre et la mise en œuvre finale, j'avais utilisé.


Basé sur les commentaires et le liés document de migration, j'ai effectué quelques modifications sur le code:

Dans le modèle:

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

Dans le script:

watch: {
  searchInput: function () {
    this.debounceInput();
  }
},

Et la méthode qui définit la clé filtre reste le même:

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

Cela ressemble à il y a un moins d'appel (juste l' v-model, et non pas l' v-on:input).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X