Как использовать анти-шейк и дроссель в Vue

внешний интерфейс JavaScript Vue.js
Как использовать анти-шейк и дроссель в Vue

Эта статья является переводом

Оригинальное название: How to Debounce and Throttle Callbacks in Vue

Автор оригинала: Дмитрий Павлютин

Оригинальный адрес:Псевдоним маппета для рисовой поездки avlutin.com/v UE-…

Будьте осторожны при прослушивании часто инициируемых событий, таких как ввод пользователем в поля ввода, изменение размера окна, прокрутка и события Intersection Observer.

Эти события всегда запускаются часто, может быть, каждые несколько секунд. Было бы неразумно делать запрос на выборку (или подобное поведение) для каждого события.

Все, что нам нужно сделать, это замедлить выполнение обработчика событий. Этот метод буферизацииДебунс и дроссель.

В этой статье вы узнаете, как использовать debounce и Throttle для управления наблюдателями и обработчиками событий в компонентах Vue.

1. Стабилизация наблюдателя

Начнем с простого компонента, наша задача вывести в консоль текст, введенный пользователем в текстовое поле:

<template>
  <input v-model="value" type="text" />
  <p>{{ value }}</p>
</template>
<script>
export default {
  data() {
    return {
      value: "",
    };
  },
  watch: {
    value(newValue, oldValue) {
      console.log("Value changed: ", newValue);
    }
  }
};
</script>

Открыть демонстрацию

Откройте демо и введите несколько символов в поле ввода. Значение регистрируется в консоли каждый раз, когда оно вводится.

Мы слушаем с помощью наблюдателяvalueАтрибут данных реализует журнал печати. Но если вы хотите добавить обратный вызов наблюдателю, используяvalueGET-запросы в качестве параметров, то не следует ожидать слишком частых запросов.

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

я выбрал здесь'lodash.debounce'Реализация анти-шейка, но вы вольны выбрать понравившуюся вам реализацию.

Давайте применим логику устранения дребезга к компоненту:

<template>
  <input v-model="value" type="text" />
  <p>{{ value }}</p>
</template>
<script>
import debounce from "lodash.debounce";
export default {
  data() {
    return {
      value: "",
    };
  },
  watch: {
    value(...args) {
      this.debouncedWatch(...args);
    },
  },
  created() {
    this.debouncedWatch = debounce((newValue, oldValue) => {
      console.log('New value:', newValue);
    }, 500);
  },
  beforeUnmount() {
    this.debouncedWatch.cancel();
  },
};
</script>

попробовать демо

Если вы откроете эту демонстрацию, вы обнаружите, что с точки зрения пользователя мало что изменилось: вы по-прежнему можете свободно вводить символы, как и в предыдущей демонстрации.

Но есть одно отличие: только последний ввод500msПосле этого новое входное значение будет записано в консоль. Это означает, что действует защита от сотрясений.

Реализация анти-встряхивания наблюдателя требует всего 3 простых шага:

  1. существуетcreate()В хуке создайте обратный вызов для защиты от сотрясений и назначьте его экземпляру:this.debouncedWatch = debounce(..., 500).
  2. в обратном вызове наблюдателяwatch.value() { ... }передать правильные параметры в вызовеthis.debouncedWatch().
  3. наконец,beforeUnmount()позвонить в крюкthis.debouncedWatch.cancel(), перед выгрузкой компонента отмените выполнение всех ожидающих выполнения функций защиты от сотрясений.

Точно так же вы можете применить debounce к наблюдателям произвольных свойств данных. Затем вы можете безопасно выполнять некоторые более тяжелые операции внутри обратного вызова, предотвращающего сотрясение, такие как сетевые запросы, тяжелые операции DOM и т. д.

2. Обработчик событий Anti-shake

В предыдущем разделе я показал, как использовать debounce с наблюдателями, но как насчет обычных обработчиков событий?

Мы повторно используем предыдущий пример, когда пользователь вводил данные в поле ввода, но на этот раз мы добавим в поле ввода обработчик событий.

Как обычно, если вы не выполняете никакой буферизации, каждый раз, когда значение изменяется, оно будет выводиться на консоль:

<template>
  <input v-on:input="handler" type="text" />
</template>
<script>
export default {
  methods: {
    handler(event) {
      console.log('New value:', event.target.value);
    }
  }
};
</script>

попробовать демо

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

Кроме того, если вы будете выполнять какие-то тяжелые операции (например, сетевые запросы), он не подходит.

Чтобы использовать защиту от сотрясений для обработчиков событий, вы можете обратиться к следующему:

<template>
  <input v-on:input="debouncedHandler" type="text" />
</template>
<script>
import debounce from "lodash.debounce";
export default {
  created() {
    this.debouncedHandler = debounce(event => {
      console.log('New value:', event.target.value);
    }, 500);
  },
  beforeUnmount() {
    this.debouncedHandler.cancel();
  }
};
</script>

попробовать демо

Откройте демо и введите несколько символов. Компоненты вводятся только после последнего500msПосле этого новое входное значение будет записано в консоль. Антишок снова работает!

Реализация debounce обработчика событий требует всего 3 шага:

  1. . существуетcreate()В хуке после создания экземпляра сразу же вызывается обратный вызов анти-шейка.debounce(event => {...}, 500)назначить наthis.debouncedHandler.
  2. В шаблоне поля ввода дайтеv-on:inputнаделятьdebouncedHandler:<input v-on:input="debouncedHandler" type="text" />
  3. Наконец, перед выгрузкой компонента, вbeforeUnmount()позвонить в крюкthis.debouncedHandler.cancel(), отменяет все ожидающие вызовы функций.

С другой стороны, в этих примерах применяется технология защиты от сотрясений. Однако тот же подход можно использовать для создания функций регулирования.

3. Обратите внимание

Вы можете не понять: почему нельзя прямо в компонентеmethodСоздать функции устранения дребезга в параметрах, а затем вызывать эти методы в шаблоне как обработчики событий?

// ...
  methods: {
    // Why not?
    debouncedHandler: debounce(function () { ... }}, 500)
  }
// ...

Это намного проще, чем создание функции устранения дребезга для экземпляра объекта.

Например:

<template>
  <input v-on:input="debouncedHandler" type="text" />
</template>
<script>
import debounce from "lodash.debounce";
export default {
  methods: {
    // Don't do this!
    debouncedHandler: debounce(function(event) {
      console.log('New value:', event.target.value);
    }, 500)
  }
};
</script>

попробовать демо

Не в этот разcreated()Обратный вызов против сотрясения создается в хуке, но обратный вызов против сотрясения назначаетсяmethods.debouncedHandler.

Если вы попробуете демо, вы обнаружите, что это работает!

Проблема в том, что компонент используетexport default { ... }Экспортированный объект параметров, включая методы, будет повторно использоваться экземпляром компонента.

Если на странице более 2 экземпляров компонента, будут применены все компонентытакой жефункция защиты от сотрясенийmethods.debouncedHandler— Это может привести к неисправности стабилизации.

4. Резюме

В Vue легко применить подавление дребезга и регулирование к наблюдателям и обработчикам событий.

Основная логика в том, что вcreated()В хуке создайте обратный вызов debounce или Throttle и назначьте его экземпляру.

// ...
  created() {
    this.debouncedCallback = debounce((...args) => {
      // The debounced callback
    }, 500);
  },
// ...

A) Затем внутри наблюдателя вызовите функцию debounce для экземпляра:

// ...
  watch: {
    value(...args) {
      this.debouncedCallback(...args);
    },
  },
// ...

Б) Или установить обработчик события в шаблоне:

<template>
  <input v-on:input="debouncedHandler" type="text" />
</template>

После этого каждый вызовthis.debouncedCallback(...args), даже если частота выполнения очень высока, внутренний обратный вызов может буферизовать выполнение.

У вас есть вопросы о стабилизации и дросселировании в Vue? Приветствуются вопросы!