menumenu_open <!— xhtml.ru —>

DOM Events — прохождение событий

DOM event flow

Прохождение события

  • Событие (DOM Event) всегда начинается от корня документа.
  • Из корня событие проходит по дереву DOM и останавливается на элементе, который вызвал событие <td>, это — цель события (event target).
  • Событие проходит по кратчайшему пути, но по мере прохождения уведомляется каждый элемент, который встретится на этом пути. Если у такого элемента есть обработчик для этого события, он будет вызван.
  • Когда событие достигает своей цели <td>, оно не останавливается.
  • Событие продолжается, оно возвращается назад к корню.
  • Каждый элемент на пути события, по мере возвращения, получает уведомление о его существовании.

Стандарт DOM Events описывают 3 фазы распространения событий

  1. Capturing phase — фаза захвата, событие следует к элементу
  2. Target phase — событие достигает целевого элемента
  3. Bubbling phase — событие возвращается обратно

Для примера из картинки это будет так:

  • Capturing phase: для клика по <td> событие сначала проходит по цепочке предков от корня до элемента
  • Target phase: достигает цели и переключается
  • Bubbling phase: событие возвращается и по пути снова вызывает свои обработчики

Event Bubbling и Capturing

Event Bubbling (по умолчанию) используется чаще всего в отличие от Event Capturing. Тем не менее, знать про обе фазы прохождения событий не будет лишним.

elem.addEventListener(..., {capture: true})
// или только "true" это алиас для {capture: true}
elem.addEventListener(..., true)

Таким образом, получаем 2 возможных варианта перехвата и обработки события:

  • false (по умолчанию), когда событие уже возвращается обратно от элемента
  • true — событие только направляется от корня документа к элементу

See the Pen
js_event
by xhtml_ru (@xhtml_ru)
on CodePen.

Клик по элементу <p>, продемонстрирует прохождение события:

  1. HTML → BODY → FORM → DIV (сapturing phase) фаза захвата, событие следует к элементу
  2. P (target phase) событие достигает целевого элемента
  3. DIV → FORM → BODY → HTML (bubbling phase) событие возвращается обратно

Что ещё нужно знать о Event Bubbling

Почти у всех событий есть bubbling phase, за редким исключением. Например, событие bubbling phase отсутствует у focus.

Что ещё нужно знать о Event Capturing

Эта фаза событий используется не часто.

Свойства события: target, currentTarget, eventPhase

target

  • относится к элементу DOM, который вызвал событие
  • оно не меняется в течение времени жизни события

currentTarget (this)

ссылка на элемент DOM, которому назначен метод-перехватчик события

See the Pen
event target vs currentTarget
by xhtml_ru (@xhtml_ru)
on CodePen.

Обработчик клика у элемента FORM будет перехватывать клики по любому элементу внутри него. Независимо от того, где произошел клик, он всплывёт до <form> и запустит обработчик. e.currentTarget здесь будет элемент <form>, потому, что ему назначен метод-обработчик. e.target
— любой элемент внутри <form>, по которому был сделан клик.

eventPhase

Свойство события eventPhase возвращает число, указывающее, какая фаза потока событий в настоящее время оценивается.

Число представлено четырьмя числовыми константами:

  1. NONE
  2. CAPTURING_PHASE поток событий находится в фазе захвата
  3. AT_TARGET поток событий находится в целевой фазе, то есть событие достигло цели
  4. BUBBLING_PHASE поток событий находится в фазе возвращения

Прерывание событий

stopPropagation()

Метод stopPropagation у объекта Event предназначен для предотвращения распространения события (bubbling). Объект Event предоставляет этот метод параметром в виде функции обратного вызова. Но лучше не останавливать событие с помощью event.stopPropagation() без особой необходимости. В большинстве случаев это бесполезно и может привести к неожиданному отсутствию события там, где возникла необходимость его обнаруживать. Иногда лучше позволить событию спокойно завершить весь свой жизненный цикл.

function handleClick(event) {
  event.stopPropagation();
  // какой-то код
}

Если у элемента есть несколько обработчиков для одного события, то когда один из них останавливает (метод stopPropagation()) распространение, другие по-прежнему выполнятся.

stopImmediatePropagation()

В отличие от stopPropagation(), вызов метода stopImmediatePropagation() остановит распространение события и предотвратит выполнение остальных обработчиков.

Итог

При возникновении, событие DOM начинает перемещаться от корня документа к элементу, который его инициировал. Доходит до элемента-инициатора и возвращается обратно. По пути к инициатору и обратно любой элемент может перехватить событие и как-то его обработать. У события есть методы для остановки его распространения. У события есть несколько свойств для идентификации его состояния в момент перехвата.