Главная » События и их обработчики

События и их обработчики


03.04.2021, 22:21
Событие - это "сигнал" от браузера о том, что что-то произошло.

Примеры: клик, двойной клик, наведение мыши, убирание мыши с элемента, прокрутка колеса мыши, отправка данных формы, нажатие клавиш на клавиатуре и другие.

Для использования любого события назначается его обработчик - функция, срабатывающая, как только событие произошло.

В JavaScript есть три способа назначения обработчиков событий.

Первый: путём использования в вёрстке html-атрибута, не используется в проектах и не рекомендован к применению:

Код

<button onclick = "alert('Hello Wolrd')">Нажми меня</button>

Второй способ: путём использования свойств DOM-дерева для событий (также почти не используется)

Код

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

btn.onclick = function() {
  alert('Hello World'); /* код выполнится после клика */
};

В данном случае .onclick это свойство DOM-дерева, которое мы применили к элементу из переменной btn

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

Код

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

btn.onclick = function() {
  alert('Hello World'); /* окно не отобразится */
};

btn.onclick = function() {
  alert('Я люблю JavaScript!'); /* окно отобразится */
};

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

Используемые методы для назначения обработчиков событий

addEventListener() - назначение обработчика события
removeEventListener() - удаление обработчика события

пример назначения обработчика события:

Код

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

btn.addEventListener('click', function() {
  /* здесь выполняемый код функции */
});

Первым аргументом идёт название события (click), вторым - каллбэк-функция, которая и будет обработчиком и будет выполняться после наступления события click

Теперь, если назначить для одного элемента два обработчика событий, отработают оба (появятся последовательно два окна):

Код

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

btn.addEventListener('click', function() {
  alert('Hello World');
});

btn.addEventListener('click', function() {
  alert('Я люблю JavaScript!');
});

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

Код

btn.addEventListener('click', () => {
  alert('Я люблю JavaScript!');
}); // => вместо события click может быть любое другое событие

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

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

Объект события event передаётся в виде первого аргумента в коллбэк-функцию, при этом называть его можно как угодно (обычно event или сокращённо e)

Код

btn.addEventListener('click', (event) => {
  alert('Я люблю JavaScript!');
}); // => вместо event можно использовать любое название

Свойство target объекта события event является ссылкой на объект, который был инициатором события. Например, при клике на кнопку, объектом-инициатором события click будет элемент button.

И теперь мы можем с этим элементом что-то делать, например, можно удалить его:

Код

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

btn.addEventListener('click', (event) => {
  event.target.remove();
}); // => при клике на кнопке, элемент исчезнет со страницы

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

Вынесем каллбэк-функцию, удаляющую элемент, в отдельную переменную deleteElement, которую передадим в обработчик

Код

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

const deleteElement = (event) => {
  event.target.remove();
};

btn.addEventListener('click', deleteElement);

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

Код

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

btn.addEventListener('click', (event) => {
  event.target.remove();
});

btn.removeEventListener('click', (event) => {
  event.target.remove();
});

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

Код

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

const deleteElement = (event) => {
  event.target.remove();
};

btn.addEventListener('click', deleteElement);
btn.removeEventListener('click', deleteElement); // => мы удалили обработчик события, кнопка не исчезнет при клике по ней

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

Всплытие событий

Если имеется вложенность элементов друг в друга, например, есть родительский элемент с классом overlay и элемент button внутри него:

Код

<div class="overlay">
  <button class="btn">Кнопка</button>
</div>

для каждого из этих двух элементов назначим обработчик события click:

Код

const overlay = document.querySelector('.overlay'),
  btn = overlay.querySelector('.btn');

  overlay.addEventListener('click', (event) => {
  console.log(event.target); /* Выводим в консоль элемент */
  console.log(event.type); /* Выводим тип события */
  });

  overlay.addEventListener('click', (event) => {
  console.log(event.target); /* Выводим в консоль элемент */
  console.log(event.type); /* Выводим тип события */
  });

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

Но при этом в консоли в качестве элемента два раза будет выведен элемент button, хотя событие отработало один раз на элементе button, а второй раз на элементе с классом overlay


Так как мы ссылаемся на event.target, то в консоли два раза вывелся элемент, на котором произошло изначально событие, то есть элемент button

Если вместо свойства target использовать свойство currentTarget, то в консоли мы увидим оба элемента, сначала button, на котором изначально произошло событие click, затем элемент с классом overlay, на котором событие произошло в результате всплытия:


Оба элемента появились в консоли

Отмена стандартного поведения браузера

Для отмены стандартного действия браузера, используется метод preventDefault() объекта event

Например, нужно отменить стандартное действие браузера при клике на ссылке (переход по ссылке).

Выбираем элемент(ссылку) со страницы и назначаем ей обработчик события click:

Код

  const link = document.querySelector('a');

  link.addEventListener('click', (event) => {
  event.preventDefault(); /* отменяем стандартное поведение браузера */
  });

Как назначить один обработчик события на несколько элементов

Допустим, на странице сайта есть несколько элементов button:

Код

  <div class="overlay">
  <button class="btn">Кнопка</button>
  <button class="btn">Кнопка</button>
  <button class="btn">Кнопка</button>
  </div>

Сначала получаем эту выборку элементов для взаимодействия с ними:

Код

const btns = document.querySelectorAll('.btn');

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

Код

const btns = document.querySelectorAll('.btn');

btns.forEach(btn => {
  btn.addEventListener('click', () => {
  console.log('Click');
  });
});

Теперь, при клике на любой элемент button в консоли будет выводиться строка "Click"

У обработчика события существует третий аргумент, опции. Например, опция once позволяет явно указать, что событие должно происходить только один раз (что является отличной альтернативой использованию метода removeEventListener() ):

Код

const btns = document.querySelectorAll('.btn');

btns.forEach(btn => {
  btn.addEventListener('click', () => {
  console.log('Click');
  }, {once: true}); /* теперь для каждой кнопки код сработает один раз */
});

КОММЕНТАРИИ (0)