У меня есть простое поле ввода в шаблоне Vue, и я хотел бы использовать debounce примерно так:
<input type="text" v-model="filterKey" debounce="500">
Однако это debounce
свойство устарело в Vue 2 . В рекомендации только сказано: «используйте v-on: input + стороннюю функцию debounce».
Как правильно это реализовать?
Я пытался реализовать это с помощью 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)
}
Затем ключ фильтра используется в computed
реквизитах.
vue.js
vuejs2
debouncing
МартинТиВарга
источник
источник
Ответы:
Я использую пакет debounce NPM и реализован так:
Используя lodash и пример в вопросе, реализация выглядит так:
источник
v-model=your_input_variable
к вводу и в вашем vuedata
. Таким образом, вы не полагаетесь наe.target
Vue, а используете его, чтобы получить доступthis.your_input_variable
вместоe.target.value
this
к ней.Назначение дебаунда
methods
может быть проблемой. Итак, вместо этого:Вы можете попробовать:
Это становится проблемой, если у вас есть несколько экземпляров компонента - аналогично тому, как
data
должна быть функция, возвращающая объект. Каждому экземпляру нужна своя собственная функция противодействия, если предполагается, что они действуют независимо.Вот пример проблемы:
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>
источник
data()
then.обновлено в 2020 году
Вариант 1: многоразовый, без депс
(Рекомендуется, если требуется более одного раза в вашем проекте)
helpers.js
Component.vue
Codepen
Вариант 2: внутрикомпонентный, также без зависимостей
(Рекомендуется при однократном использовании или в небольшом проекте)
Component.vue
Codepen
источник
Очень просто без lodash
источник
destroyed() { clearInterval(this.timeout) }
, чтобы не было тайм-аута после уничтожения.У меня была такая же проблема, и вот решение, которое работает без плагинов.
Поскольку
<input v-model="xxxx">
точно так же, как(источник)
Я подумал, что могу установить функцию противодействия при назначении xxxx в
xxxx = $event.target.value
как это
методы:
источник
@input="update_something"
действие, назовите его послеthat.xxx = val
that.update_something();
debounceSearch: function(val) { if (this.search_timeout) clearTimeout(this.search_timeout); var that=this; this.search_timeout = setTimeout(function() { that.thread_count = val; that.update_something(); }, 500); },
На основе комментариев и связанного документа по миграции я внес несколько изменений в код:
В шаблоне:
В скрипте:
И метод, устанавливающий ключ фильтра, остается прежним:
Похоже, на один вызов меньше (только на
v-model
, а не наv-on:input
).источник
debounceInput()
дважды для каждого изменения?v-on:
обнаружит входные изменения и вызовет debounce, И поскольку модель привязана, функция наблюдения searchInput ТАКЖЕ вызоветdebounceInput
... верно?Если вам нужен очень минималистичный подход к этому, я сделал его (первоначально созданный из vuejs-tips для поддержки IE), который доступен здесь: https://www.npmjs.com/package/v-debounce
Применение:
Затем в вашем компоненте:
источник
Если вам нужно применить динамическую задержку с функцией lodash
debounce
:И шаблон:
ПРИМЕЧАНИЕ: в приведенном выше примере я сделал пример ввода для поиска, который может вызывать API с настраиваемой задержкой, которая предоставляется в
props
источник
Хотя почти все ответы здесь уже верны, если кто-то ищет быстрое решение, у меня есть директива для этого. https://www.npmjs.com/package/vue-lazy-input
Он применяется к @input и v-model, поддерживает настраиваемые компоненты и элементы DOM, debounce и throttle.
Vue.use(VueLazyInput) new Vue({ el: '#app', data() { return { val: 42 } }, methods:{ onLazyInput(e){ console.log(e.target.value) } } })
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <script src="https://unpkg.com/lodash/lodash.min.js"></script><!-- dependency --> <script src="https://unpkg.com/vue-lazy-input@latest"></script> <div id="app"> <input type="range" v-model="val" @input="onLazyInput" v-lazy-input /> {{val}} </div>
источник
Если вы используете Vue, вы также можете использовать его
v.model.lazy
вместо,debounce
но помните, чтоv.model.lazy
он не всегда будет работать, поскольку Vue ограничивает его для пользовательских компонентов.Для пользовательских компонентов вы должны использовать
:value
вместе с@change.native
<b-input :value="data" @change.native="data = $event.target.value" ></b-input>
источник
Если бы вы могли перенести выполнение функции debounce в какой-нибудь метод класса, вы могли бы использовать декоратор из utils-decorators lib (
npm install --save utils-decorators
):источник
Мы можем обойтись с помощью нескольких строк JS-кода:
Простое решение! Отличная работа! Надеюсь, вам будет полезно, ребята.
источник
vue-свойство-декоратор
источник