Подія в DOM проходить три фази:
- Перехоплення (capture) - від
windowвниз до цільового елемента. - Ціль - на самому елементі.
- Спливання (bubble) - назад угору до
window.
Обробники за замовчуванням спрацьовують на фазі спливання. Тому клік по кнопці в картці «бачать» і кнопка, і картка, і document.
Делегування - один обробник на спільному предку замість обробника на кожному елементі:
document.querySelector('#todo-list').addEventListener('click', (event) => {
const button = event.target.closest('[data-action="delete"]');
if (!button) return;
removeTodo(button.dataset.id);
});
Переваги:
- Працює для елементів, доданих пізніше (підвантажені рядки, нові пункти списку) - не треба вішати обробники заново.
- Один обробник замість тисячі - менше пам'яті й простіше прибирання.
Що треба знати:
event.target- елемент, на якому подія виникла (може бути<span>всередині кнопки).event.currentTarget- елемент, на якому висить обробник. Звідсиclosest()у прикладі.stopPropagation()зупиняє спливання, але ламає делегування й аналітику вище за деревом. Використовувати обережно.- Не всі події спливають:
focus/blur- ні (зате спливаютьfocusin/focusout),mouseenter/mouseleave- ні (спливаютьmouseover/mouseout).