Курс →React JS

для начинающих
от платформы StackDev.ru

Обработчики Событий в JS (как работает addEventListener)

Дата:
Javascript

В этой статье мы с вами разберемся как правильно использовать обработчики событий (addEventListener) в Javascript на различных элементах DOM дерева страниц. Эти элементы могут включать кнопки, ссылки, изображения и так далее.

Любой DOM элемент запускает событие, когда мы с ним как-то взаимодействуем (кликаем, наводим мышь и др.). Обработчики событий в JS используются для того, чтобы реагировать на эти события.

Обработчики событий можно "вешать" на любые элементы DOM (Data Object Model) дерева, а также глобальные объекты window и document.

Предположим, на нашей странице есть html элемент button с классом "btn":

1<div class="wrapper">
2 <button class="btn">Click</button>
3</div>

Давайте выделим наш элемент button и присвоим его переменной button:

1const button = document.querySelector('.btn');

Чтобы "повесить" обработчик событий на наш элемент button, нужно использовать специальный метод - addEventListener. Этот метод принимает 2 аргумента:

  1. Тип события (мы будем "слушать" событие "click").
  2. Так называемую колбэк (callback) функцию, которая запускается после срабатывания нужного события.

Колбэк функция (callback function) - отличается от обычной функции, тем, что ее запускаем не мы, а браузер, который делает это после срабатывания события.

1const button = document.querySelector('.btn');
2button.addEventListener('click', function () {
3 console.log('click');
4});

Таким образом, каждый раз после срабатывания события "click" будет запускаться наша коллбэк функция и мы будем получать строку "click" в нашей консоли.

Обработчики событий JS (выносим логику коллбэк функции за пределы метода addEventListener)

Мы также можем вынести нашу коллбэк функцию за пределы метода addEventListener, а внутри обработчика событий просто ссылаться на нее:

1const button = document.querySelector('.btn');
2
3function handleClick() {
4 console.log('click');
5}
6button.addEventListener('click', handleClick);

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

Давайте использовать готовую логику в функции handleClick - для новой кнопки:

1<div class="wrapper">
2 <button class="btn">Click</button>
3 <button class="btnTwo">Click 2</button>
4</div>
1const button = document.querySelector('.btn');
2const buttonTwo = document.querySelector('.btnTwo');
3
4function handleClick() {
5 console.log('click');
6}
7button.addEventListener('click', handleClick);
8
9// Вешаем обработчик событий с готовой логикой на новую кнопку
10buttonTwo.addEventListener('click', handleClick);

Как снять обработчик события addEventListener с элемента?

Чтобы снять обработчик события с какого-либо элемента, нужно использовать метод removeEventListener. В качестве аргументов нужно указать не только название события ("click"), но и название коллбэк функции, которая привязана к элементу.

1buttonTwo.removeEventListener('click', handleClick);

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

Обработка событий на нескольких DOM элементах

Как использовать обработчик событий addEventListener, когда нам требуется использовать его сразу на нескольких элементах?

Предположим, на нашей странице есть 5 кнопок с классом "btn":

1<div class="wrapper">
2 <button class="btn">Click 1</button>
3 <button class="btn">Click 2</button>
4 <button class="btn">Click 3</button>
5 <button class="btn">Click 4</button>
6 <button class="btn">Click 5</button>
7</div>

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

Подход 1. Используем отдельный addEventListener для каждой кнопки

Здесь мы можем выделить все кнопки с одинаковым классом и присвоить их переменной buttons. Далее нам потребуется использовать цикл forEach, чтобы пробежаться по каждой кнопке в полученном списке, и повесить на нее обработчик событий addEventListener.

1const buttons = document.querySelectorAll('.btn');
2
3function handleClick() {
4 console.log('click');
5}
6
7buttons.forEach((button) => {
8 button.addEventListener('click', handleClick);
9});

Подход 2. Делегирование события (Event delegation)

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

То есть, мы можем повесить обработчик событий на родительский div с классом "wrapper", и обрабатывать события, которые активируются на дочерних элементах button.

Это возможно благодаря механизму, который называется "всплытие" (bubbling) в Javascript, который означает, что если событие срабатывает на каком-то элементе, оно также срабатывает на всех его родительских элементах.

Внутри нашей коллбэк функции у нас есть доступ к объекту "Событие" (Event), внутри которого мы можем использовать свойство target, чтобы получить элемент, на который мы кликнули.

1const wrapper = document.querySelector('.wrapper');
2
3function handleClick(e) {
4 console.log('click', e.target);
5 // При клике получаем каждый конкретный элемент button
6 // click <button class="btn">Click 1</button>
7 // click <button class="btn">Click 2</button>
8}
9
10wrapper.addEventListener('click', handleClick);