Как реализовать debounce в Vue2?

у меня есть простое поле ввода в шаблоне Vue, и я хотел бы использовать debounce более или менее так:

<input type="text" v-model="filterKey" debounce="500">
на debounce имущество устарел в Vue 2. В рекомендации говорится только: "используйте функцию v-on:input + 3rd party debounce".

как вы правильно это реализовать?

Я попытался реализовать его с помощью лодашь, v-on: вход и v-модель, но я интересно, можно ли обойтись без дополнительной переменной.

в шаблоне:

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

в скрипт:

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

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

filterkey затем используется позже в computed бутафория.

4 ответов


Я использую debounce пакет NPM и реализован следующим образом:

<input @input="debounceInput">

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

используя лодашь и пример в вопросе, реализация выглядит следующим образом:

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

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

назначение debounce в methods могут быть проблемы. Поэтому вместо этого:

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

можно попробовать:

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

это становится проблемой, если у вас есть несколько экземпляров компонента - аналогично data должна быть функция, которая возвращает объект. Каждый экземпляр нуждается в своей собственной функции debounce, если они должны действовать независимо. Пример


обратите внимание, что я разместил этот ответ, прежде чем принято отвечать. Это не правильный. Это всего лишь шаг вперед от решения в вопрос. Я отредактировал принятый вопрос, чтобы показать как реализацию автора, так и окончательную реализацию, которую я использовал.


на основе комментариев и связанный миграционный документ, я внес несколько изменений в код:

в шаблоне:

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

In сценарий:

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

и метод, который устанавливает ключ фильтра, остается тем же:

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

похоже, что на один вызов меньше (только v-model, а не v-on:input).


Если вам нужен очень минималистичный подход к этому, я сделал один (первоначально раздвоенный из VueJS-советов, чтобы также поддерживать IE), который доступен здесь:https://www.npmjs.com/package/v-debounce

использование:

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

затем в компоненте:

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