DevGang
Авторизоваться

Делегирование событий и множественные селекторы с ванильным JS

Сегодня мы рассмотрим подходы к использованию делегирования событий с несколькими селекторами.

Как это работает

Если вы не знакомы с подходом, вот как это работает. Вместо того, чтобы прикреплять события к определенным элементам, вы прослушиваете это событие в родительском элементе (часто это document или window).

Любое событие такого типа, которое происходит внутри родительского элемента, всплывает, и вы можете отфильтровать те, которые не соответствуют элементу, который вы ищете.

document.addEventListener('click', function (event) {
  if (!event.target.matches('.click-me')) return;
});

Если вы прослушиваете события для более чем одного элемента с одним и тем же селектором, этот подход на самом деле лучше для производительности, поскольку он использует меньше памяти в браузере.

Несколько селекторов

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

Например, предположим, что у вас есть кнопки отображения / скрытия содержимого, на которых есть класс .show-me, и другой набор кнопок с классом .save, которые сохраняют содержимое формы для повторного использования позже.

Как вы анализируете, какие действия запускать на основе селектора?

Вариант 1: отдельные слушатели событий

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

document.addEventListener('click', function (event) {
  if (!event.target.matches('.show-me')) return;
});

document.addEventListener('click', function (event) {
  if (!event.target.matches('.save')) return;
});

Этот подход хорошо работает, если ваши скрипты хранятся в отдельных модульных файлах.

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

Вариант 2: if...else

Если оба фрагмента кода находятся в одном файле, вы можете объединить их в один слушитель событий и использовать оператор if...else if.

document.addEventListener('click', function (event) {
  if (event.target.matches('.show-me')) {
    // ...
  } else if (event.target.matches('.save')) {
    // ...
  }
});

Это дает вам небольшой прирост производительности.

Вариант 3: if и return

Многие люди считают if...else if громоздкими, особенно если у вас есть больше, чем просто пара проверок. Они могут быстро вырасти и выйти из-под контроля.

По этой причине я предпочитаю использовать последовательные операторы if с return для завершения функции при совпадении.

document.addEventListener('click', function (event) {
  if (event.target.matches('.show-me')) {
    // ...
    return;
  }
  
  if (event.target.matches('.save')) {
    // ...
    return;
  }
});

Этот подход для меня легче читать. Это также означает, что я могу перемещать свои проверки, не беспокоясь о том, чтобы что-нибудь сломать.

Вариант 4: функции обработчика

Если вам нравится функциональное программирование , этот подход обеспечивает хорошую структуру.

Внутри обратного вызова слушателя событий вы вызываете отдельные функции-обработчики для каждого селектора и передаете объект event. В каждой функции-обработчике вы запускаете проверку селектора и запускаете код соответственно.

var showMe = function (event) {
  if (!event.target.matches('.show-me')) return;
    // ...
};

var saveMe = function (event) {
  if (!event.target.matches('.save')) return;
    // ...
};

document.addEventListener('click', function (event) {
  showMe(event);
  saveMe(event);
});

Такой подход обеспечивает хороший баланс производительности и ремонтопригодности.

Это немного менее производительней, чем варианты 2 и 3, потому что функция saveMe() будет работать, даже если showMe() найдет совпадение (два других подхода останавливаются, как только найдено совпадение). Но это все же лучше, чем иметь отдельных слушателей событий, и обеспечивает чистую, читаемую структуру кода.

#JavaScript
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться