Что такое event bubbling и event capturing в JavaScript
Что проверяют
Знаете ли вы, что у события три фазы, и умеете ли этим пользоваться, прежде всего для делегирования. Следом обычно спрашивают разницу между stopPropagation и preventDefault или просят повесить один обработчик на список из тысячи элементов.
Как отвечать
Событие DOM проходит три фазы:
- погружение (capturing): от
windowчерезdocumentвниз по предкам к целевому элементу; - цель (target): событие на самом элементе, по которому кликнули;
- всплытие (bubbling): обратный путь от цели вверх до
window.
По умолчанию addEventListener слушает всплытие. Чтобы поймать событие на погружении, передают третий аргумент true или { capture: true }. Значит, если родитель слушает с capture: true, а кнопка обычно, при клике по кнопке сначала сработает родитель, потом кнопка.
Управление распространением:
stopPropagation(): останавливает движение по дереву, но остальные обработчики на том же элементе сработают;stopImmediatePropagation(): вдобавок отменяет оставшиеся обработчики на текущем элементе;preventDefault(): отменяет действие браузера (переход по ссылке, отправку формы) и распространение не трогает.
Главное практическое применение всплытия это делегирование: один обработчик на ul вместо сотни на li, нужный пункт ищут через event.target.closest('li'). Важно различать event.target, исходный элемент, и event.currentTarget, элемент, на котором висит обработчик.
Не все события всплывают: focus, blur, mouseenter и mouseleave не всплывают, для делегирования фокуса есть focusin и focusout. В React обработчики тоже делегируются на корневой контейнер, а для фазы погружения есть пропсы вида onClickCapture.
Где спотыкаются
Путают порядок и говорят, что при capture: true на родителе первой сработает кнопка. На деле родитель на погружении срабатывает раньше, эта ошибка есть даже в шпаргалках.
Путают stopPropagation и preventDefault и пытаются первым отменить отправку формы.
Бездумно гасят всплытие. После stopPropagation ломаются чужие обработчики выше по дереву: закрытие выпадающих меню по клику снаружи, аналитика, делегирование внутри библиотек.