На какой фазе срабатывает обработчик события при всплытии в DOM
Что проверяют
Знаете ли вы, что всплытие это третья фаза и что именно она включена по умолчанию. Вопрос простой, но по ответу видно, разбирались ли вы в модели событий или собирали интерфейсы наугад.
Как отвечать
Событие проходит три фазы: погружение от window к цели, фаза цели, всплытие от цели вверх по предкам до document и window. Обработчик, подписанный обычным addEventListener без третьего аргумента, срабатывает именно во всплытии, и event.eventPhase в нём равен трём, то есть Event.BUBBLING_PHASE.
parent.addEventListener("click", () => console.log("parent"));
child.addEventListener("click", () => console.log("child"));
// клик по child: сначала child, затем parentНа этом держится делегирование: обработчик вешают на контейнер, а нужный элемент достают через event.target.closest(...). На этом же работает закрытие выпадающих меню по клику вне, когда слушают document, куда всплывает почти всё.
Остановить подъём можно через event.stopPropagation(), а если нужно отсечь и соседние обработчики на том же элементе, то stopImmediatePropagation().
Где спотыкаются
Считают, что всплывает любое событие. У события есть флаг bubbles, и у focus, blur, mouseenter и mouseleave он выключен. Вместо первых двух слушают focusin и focusout.
Путают stopPropagation и preventDefault. Первый останавливает движение события по дереву, второй отменяет действие браузера по умолчанию, и одно не заменяет другое. Привычка ставить stopPropagation на всякий случай ломает делегирование уровнем выше, включая чужие библиотеки.
Ждут всплытия по видимой вложенности. Событие идёт по дереву узлов, а не по картинке на экране: блок, вынесенный в конец body, всплывает в body. У React своя тонкость, его синтетические события поднимаются по дереву компонентов, поэтому клик внутри портала доходит до родителя из разметки.