vue.js vuejs2 debouncing

vue.js - ¿Cómo implementar debounce en Vue2?



vuejs2 debouncing (10)

Tengo un cuadro de entrada simple en una plantilla Vue y me gustaría usar debounce más o menos así:

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

Sin embargo, la propiedad debounce ha quedado en desuso en Vue 2 . La recomendación solo dice: "use v-on: input + función de rebote de terceros".

¿Cómo lo implementas correctamente?

Intenté implementarlo usando lodash , v-on: input y v-model , pero me pregunto si es posible prescindir de la variable adicional.

En plantilla:

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

En script:

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

La clave de filtro se usa luego en accesorios computed .


Tenga en cuenta que publiqué esta respuesta antes de la respuesta aceptada. No es correcto. Es solo un paso adelante de la solución en la pregunta. He editado la pregunta aceptada para mostrar tanto la implementación del autor como la implementación final que había utilizado.

Según los comentarios y el vuejs.org/v2/guide/… , he realizado algunos cambios en el código:

En plantilla:

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

En script:

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

Y el método que establece la clave de filtro permanece igual:

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

Parece que hay una llamada menos (solo el v-model , y no la entrada v-on:input .


Asignar un rebote en los methods puede ser un problema. Entonces, en lugar de esto:

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

Puedes probar:

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

Se convierte en un problema si tiene varias instancias de un componente, similar a la forma en que los data deberían ser una función que devuelve un objeto. Cada instancia necesita su propia función antirrebote si se supone que debe actuar de forma independiente.

Aquí hay un ejemplo del problema:

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>


En caso de que necesite aplicar un retraso dinámico con la función antirrebote de 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) { // ... } }

Y la plantilla:

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

NOTA: en el ejemplo anterior, hice un ejemplo de entrada de búsqueda que puede llamar a la API con un retraso personalizado que se proporciona en props


Estoy usando el paquete debounce NPM e implementado así:

<input @input="debounceInput"> methods: { debounceInput: debounce(function (e) { this.$store.dispatch(''updateInput'', e.target.value) }, config.debouncers.default) }

Usando lodash y el ejemplo en la pregunta, la implementación se ve así:

<input v-on:input="debounceInput"> methods: { debounceInput: _.debounce(function (e) { this.filterKey = e.target.value; }, 500) }


Muy simple sin lodash

handleScroll: function() { if (this.timeout) clearTimeout(this.timeout); this.timeout = setTimeout(() => { // your action }, 200); }


Podemos hacerlo usando pocas líneas de código JS:

if(typeof window.LIT !== ''undefined'') { clearTimeout(window.LIT); } window.LIT = setTimeout(() => this.updateTable(), 1000);

¡Solución simple! Trabajo perfecto! Espero que sea útil para ustedes.


Reutilizable y sin profundidad:

helpers.js

module.exports = 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) } }

.vue

<script> import debounce from ''./helpers'' export default { data () { return { input: '''', debouncedInput: '''' } }, watch: { input: debounce(function (newVal) { this.debouncedInput = newVal }, 500) } } </script>

(crédito a pequeño rebote )


Si está usando Vue, también puede usar v.model.lazy lugar de debounce pero recuerde que v.model.lazy no siempre funcionará ya que Vue lo limita para componentes personalizados.

Para componentes personalizados, debe usar :value junto con @change.native

<b-input :value="data" @change.native="data = $event.target.value" ></b-input>


Si necesita un enfoque muy minimalista para esto, hice uno (originalmente bifurcado de vuejs-tips para que también sea compatible con IE) que está disponible aquí: https://www.npmjs.com/package/v-debounce

Uso:

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

Luego en su componente:

<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>


Tuve el mismo problema y esto funcionó sin complementos .

Dado que <input v-model="xxxx"> es exactamente lo mismo que

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

(source)

Pensé que podría establecer una función antirrebote en la asignación de xxxx en xxxx = $event.target.value

Me gusta esto

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

métodos:

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