Какие стадии существуют у событий в DOM
Что проверяют
Знаете ли вы, что событие ходит по дереву в обе стороны, и пользуетесь ли этим, а не только вешаете обработчик на кнопку. Дальше почти всегда просят объяснить делегирование и разницу event.target и event.currentTarget.
Как отвечать
- погружение (capturing): событие идёт от
windowчерез предков вниз до целевого элемента. Обработчики вешаются третьим аргументомtrueили{ capture: true }; - цель (target): событие на самом элементе. Здесь срабатывают обработчики обеих фаз в порядке навешивания, а
event.eventPhaseравен 2; - всплытие (bubbling): обратный путь наверх до
window, поведениеaddEventListenerпо умолчанию. - не всплывают:
focus,blur,load,mouseenter,mouseleave(bubbles === false). Для делегирования фокуса берутfocusinиfocusout. Но и невсплывающее событие ловится на предке в фазе погружения; targetиcurrentTarget: первый это элемент, где произошло действие, второй это элемент с обработчиком. У стрелочной функцииthisсcurrentTargetне совпадает;- остановка:
stopPropagation()прекращает обход дерева дальше,stopImmediatePropagation()ещё и не даёт сработать остальным обработчикам на этом элементе.preventDefault()распространение не трогает, он отменяет действие браузера; - опции:
once,passive(обещание не зватьpreventDefault, дляwheelиtouchstartна корневых узлах он включён сам),signalотAbortControllerдля снятия обработчика; - Shadow DOM: наружу событие выходит с перецеленным
target, им становится хост, а реальный путь показываетevent.composedPath().
Делегирование объясняется через те же фазы: один слушатель на контейнере, event.target.closest('.item') внутри, и новые элементы работают без перевешивания.
Где спотыкаются
Ставят stopPropagation() «чтобы не мешало» и ломают чужой код: закрытие модалки по клику снаружи, аналитику на document, закрытие списка. Обычно нужна проверка closest, а не остановка события.
Считают, что путь события начинается на document. Он начинается и заканчивается на window.
Забывают, что в пассивном обработчике preventDefault() игнорируется с предупреждением в консоли.