Недавно я работал над проектом по рефакторингу внешнего интерфейса со своей командой (надеюсь, я напишу об этом статью и дам ссылку на нее здесь). Одна из техник, которую я использую чаще, чем когда-либо, — это устранение дребезга.
Ситуация
У нас есть анимированный компонент, одна из его функций — показывать подробную карточку, когда пользователь наводит мышь на целевой дом.
Выше показан визуальный захват перед рефакторингом, вы могли видеть, когда моя мышь быстро пересекает эти заголовки, вся подробная карточка выскакивает, это неприятно для моих глаз.
Когда я закончил рефакторинг, это выглядело так:
Я добился того, что пользователь с большей вероятностью увидит всплывающую карточку, когда он действительно хочет ее проверить, а не случайное срабатывание, когда пользователь просто перемещает мышь путь, который пересекает целевой дом.
Функция отката
Отмена дребезга в основном означает остановку многократного вызова функции в течение короткого промежутка времени. Например. когда вы вводите несколько слов в поле поиска, которое регистрирует событие onChange для запуска поиска, вы не хотели бы, чтобы функция поиска запускалась 50 раз, когда вы вводите «что устраняет дребезг» в поле поиска.
И функция устранения дребезга — это декоратор функции, который управляет переданной ему функцией, чтобы она выполнялась только через определенное время. Простая функция устранения дребезга, которую я бы написал, выглядит следующим образом:
Эта функция берет вашу исходную функцию fn и помещает ее в функцию замыкания, которая содержит тайм-аут, чтобы решить, должна ли она вызывать вашу исходную функцию fn при вызове этой функции.
И когда я использую его, используя функцию поиска в качестве примера (обратите внимание, что задержка настраивается):
теперь, когда вы вызываете this.search(), действие поиска не будет запускаться каждый раз, оно будет запускаться только тогда, когда вы остановили действие ввода на 300 мс.
Комплексное решение
Вернемся к первому примеру с анимацией. Как мне добиться этого с помощью устранения дребезга?
В ситуации до рефакторинга мы просто зарегистрировали события mouseEnter и mouseOut с помощью функции, подобной следующей:
В этом случае, когда пользователь перемещает мышь через целевой дом, сначала срабатывает mouseEnter и вызывается changeStatus(true),поэтому карточка выскакивает. Затем почти сразу же срабатывает событие mouseOut и вызывается changeStatus(false), поэтому карточка внезапно исчезает.
После рефакторинга кода функция стала такой:
теперь мы привязываем функцию toggleContent к событиям мыши, когда пользователь перемещает мышь через целевой дом, mouseEnter срабатывает первым и вызывается toggleContent(true), но функция changeStatus не будет вызываться еще через 100 мс. Затем, если событие mouseOut сработает и вызовет toggleContent(false) менее чем за 100 мс, везде не будет всплывающих карточек.
А теперь делайте выводы сами, я выбыл.