Далее на странице...
- Обработчик для общего родителя На каком объекте случилось событие? 1. console.dir(event.target) 2. Проверка по тегу - свойство tagName
- Пример делегирования событий Проверка на существование event.target Проверка по классу - свойство classList
- Когда используется делегирование событий? 1. События на множестве элементов 2. Интерактивные элементы
- Метод matches - Наличие класса у элемента Поиск по совпадению элемент.matches('селектор');
Делегирование событий в JS - что это такое?
Суть Делегирования событий заключается в следующем: если есть много похожих элементов, события на которых нужно обрабатывать также похожим/одинаковым образом, то вместо того, чтобы назначить обработчик события каждому элементу, создается один обработчик для общего родителя.
Событие делегируется - передается от родителя к дочерним элементам.
Обработчик для общего родителя
Есть несколько кнопок. Нужно, чтобы при клике по любой из них срабатывал один и тот же обработчик. Можно этот обработчик назначить отдельно для каждой кнопки. Но это не всегда удобно и правильно.
Далее будет назначен один обработчик для события клика - для одного элемента (это серый прямоугольник), который является родительским по отношению ко всем кнопкам. При клике на область этого элемента, нужно будет проверить - на чём именно произошел клик.
Исходный HTML-код
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>JavaScript</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="first" class="btn-block">
<button class="blue some"></button>
<button></button>
<button></button>
<button></button>
<button></button>
<button></button>
<button></button>
<button></button>
</div>
<script src="script.js"></script>
</body>
</html>
JavaScript-код
'use strict';
// Получаем все кнопки и родительский элемент
const btns = document.querySelectorAll('button'),
wrapper = document.querySelector('.btn-block');
// Назначаем обработчик для родителя
// И выводим свойства элемента, на котором произошел клик
wrapper.addEventListener('click', (event) => {
console.dir(event.target);
});
Результат в консоли
div#first.btn-block
button
accessKey: ""
ariaAtomic: null
.....
tagName: "BUTTON"
.....
Результат в Браузере
Итак, как узнать, что клик произошел именно на кнопке, а не, например, на пустой области родителя.
1. Назначаем для родителя обработчик события. При этом передаем в стрелочную функцию объект-события.
2. Чтобы получить доступ к элементу страницы, с которым происходило взаимодействие - воспользуемся свойством target объекта Event.
3. Команда console.dir позволяет вывести свойства элемента страницы, с которым происходило взаимодействие.
Console.dir - это способ посмотреть в консоли свойства заданного JS-объекта.
console.dir(object);
4. При клике на пустой области родителя - в консоли мы увидим div#first.btn-block. То есть взаимодействие происходит с , укоторого id="first" и class="btn-block". Это и есть родительский элемент.
5. При клике на любой из кнопок - в консоли мы увидим button.
И если раскрыть список свойств этого элемента страницы, то свойство tagName - позволит нам понять, что взаимодействие/клик был сделан именно по кнопке: tagName: "BUTTON".
Пример делегирования событий
Выше было разобрано, как выяснить - на каком элементе произошло событие/клик: на пустой области родителя или же на одном из дочерних (отслеживаемых) элементов.
Далее делается проверка - составляется условие.
Пример 1.1
JavaScript-код
'use strict';
// Получаем все кнопки и родительский элемент
const btns = document.querySelectorAll('button'),
wrapper = document.querySelector('.btn-block');
// Составляется условие - Если event.target существует и...
// ... клик делается по кнопке, то...
wrapper.addEventListener('click', (event) => {
if (event.target && event.target.tagName == 'BUTTON'){
console.log('Hello');
}
});
Результат в консоли
Hello
Если клик делается именно по кнопке - то в консоли мы увидим 'Hello'. Это классический пример делегирования событий в JavaScript.
Для чего в условии прописывается event.target?
Дело в том, что в HTML не все элементы поддерживают событие "клика". Некоторые теги нельзя кликнуть и поэтому для них не будет существовать целевой элемент event.target.
Поэтому, чтобы скрипт выше всегда срабатывал - делается проверка на существование event.target.
Проверка по классу - свойство classList
Используя метод contains свойства classList можно проверить наличие класса у элемента.
Пример 1.2
JavaScript-код
'use strict';
// Получаем все кнопки и родительский элемент
const btns = document.querySelectorAll('button'),
wrapper = document.querySelector('.btn-block');
// Делается проверка на наличие класса у элемента
wrapper.addEventListener('click', (event) => {
if (event.target && event.target.classList.contains('blue')){
console.log('blue');
}
});
Результат в консоли
blue
Результат в Браузере
При клике по первой кнопке - в консоли мы увидим blue.
Итак, что такое Делегирование событий? Что при этом происходит?
Мы делегируем - передаем событие с/от родителя на его потомков.
Когда используется делегирование событий?
Для чего нужно и когда используется делегирование событий?
Делегирование событий в JavaScript используется, если возникает необходимость отслеживать события на множестве элементов - в нашем случае кнопок.
Делегирование событий стоит применять, когда приходится работать с большим кол-вом интерактивных элементов: которые могут удаляться и добавляться.
Вернемся к нашему примеру и рассмотрим ситуацию, при которой:
1. Новая кнопка добавляется, когда используется делегирование событий, т.е. отслеживание события происходит через родителя.
2. Новая кнопка добавляется, когда обработчик события назначается для каждой кнопки отдельно - при помощи метода перебора forEach.
Новая кнопка - Делегирование событий
Пример 2.1
JavaScript-код
'use strict';
const btns = document.querySelectorAll('button'),
wrapper = document.querySelector('.btn-block');
wrapper.addEventListener('click', (event) => {
if (event.target && event.target.tagName == 'BUTTON'){
console.log('Hello');
}
});
// Создание кнопки, добавление к ней класса и вставка кнопки на страницу
const btn = document.createElement('button');
btn.classList.add('red');
wrapper.append(btn);
Результат в консоли
Hello
Результат в Браузере
Как видно из примера делегирование событий позволяет отслеживать события, когда мы имеем дело с интерактивными элементами: в нашем случае - это добавление новой кнопки. То есть обработчик срабатывает при возникновении события и на вновь появившемся элементе.
Новая кнопка - Метод перебора forEach
Пример 2.2
JavaScript-код
'use strict';
const btns = document.querySelectorAll('button'),
wrapper = document.querySelector('.btn-block');
// Перебираем все кнопки и...
//... назначаем для каждой из них обработчик
btns.forEach( (item) => {
item.addEventListener('click', () => {
console.log('Hello');
});
});
// Создание кнопки, добавление к ней класса и вставка кнопки на страницу
const btn = document.createElement('button');
btn.classList.add('red');
wrapper.append(btn);
Результат в Браузере
Из примера видно, что когда обработчик события назначается для каждой кнопки отдельно, то при последующем добавлении нового элемента/кнопки - обработчик не срабатывает при клике по ней.
Метод matches - Наличие класса у элемента
Выше при делегировании событий - для отслеживания события клика на дочерних элементах мы проверяли, что:
1. Клик делается по одной из кнопок - при помощи свойства tagName мы получали название тега/элемента страницы.
2. Клик делается по конкретной кнопке, у которой есть определенный класс - при этом использовался метод contains свойства classList.
Есть еще один способ отследить событие/выяснить, с каким элементом оно произошло. Это поиск по совпадению: наличие класса у определенного элемента. И это уже более продвинутое Делегирование.
Метод matches позволяет проверить, удовлетворяет ли элемент указанному CSS селектору.
элемент.matches('селектор');
Вернемся к примеру 2.1
Пример 3.1
JavaScript-код
'use strict';
const btns = document.querySelectorAll('button'),
wrapper = document.querySelector('.btn-block');
// Отслеживаем событие на кнопке с классом 'red'
wrapper.addEventListener('click', (event) => {
if (event.target && event.target.matches('button.red')){
console.log('Hello');
}
});
// Создание кнопки, добавление к ней класса и вставка кнопки на страницу
const btn = document.createElement('button');
btn.classList.add('red');
wrapper.append(btn);
Результат в Браузере
В результате обработчик срабатывает при возникновении события/при клике на кнопке с классом 'red'. event.target.matches('button.red').