Всплытие и погружение (перехват) событий DOM

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

  1. фаза погружения (capturing phase) – событие сначала идёт сверху вниз;
  2. фаза цели (target phase) – событие достигло целевого(исходного) элемента;
  3. фаза всплытия (bubbling stage) – событие начинает всплывать.

Наиболее распространено использование фазы всплытия, другие стадии, как правило, не используются  (2-ую фазу, «фазу цели»: событие достигло элемента, нельзя обработать отдельно, при её достижении вызываются все обработчики: и на всплытие, и на погружение).

Подробнее

Иллюстрация погружения и всплытия события из спецификации:

Всплытие событий JS

При наступлении события элемент, на котором оно произошло, помечается как «целевой» (event.target). Затем событие сначала двигается сверху вниз от корня документа document к event.target (целевому элементу), на каждом уровне (дочернем элементе) вызывая обработчики, назначенные через addEventListener(type, listener, true), где true – это сокращение для {capture: true}.

При достижении целевого элемента обработчики вызываются на целевом элементе event.target.

Затем событие начинает "всплывать", т.е. двигается от event.target вверх к корню документа, по пути вызывая обработчики, назначенные с префиксом on (например, onclick) или через addEventListener(type, listener, false) (или без третьего аргумента).

Каждый обработчик имеет доступ к свойствам события event:

  • event.target – самый глубокий элемент, на котором произошло событие;
  • event.currentTarget (== this) – элемент, на котором в данный момент сработал обработчик (тот, которомe назначен конкретный обработчик);
  • event.eventPhase – фаза, на которой сработал обработчик (1 - погружение, цели - 2, всплытие - 3).

Любой обработчик может остановить событие вызовом методов:

  1. event.stopPropagation() - препятствует дальнейшему всплытию события дальше по цепочке элементов;
  2. event.stopImmediatePropagation()  не только предотвращает всплытие, но и останавливает обработку событий на текущем элементе.

[свернуть]

Всплытие событий DOM

Всплытие событий DOM - это процесс последовательного срабатывания обработчиков события вверх по цепочке "родителей", начиная с объекта DOM, инициировавшего событие, до объекта document.

Пример (learn.javascript.ru):

Например, есть 3 вложенных элемента FORM > DIV > P с обработчиком на каждом:

Клик по внутреннему <p> вызовет обработчик onclick:

  1. сначала на самом <p>;
  2. потом на внешнем <div>;
  3. затем на внешнем <form>, и т.д. вверх по цепочке до самого document.

Поэтому если кликнуть на <p>, то мы увидим три оповещения: p → div → form (события «всплывают» от внутреннего элемента вверх через родителей подобно тому, как всплывает пузырёк воздуха в воде).

Элемент, который вызывает событие, называется целевым элементом, и он доступен через свойство event.target.

Отличие event.target от this:

  • event.target – это элемент, на котором произошло событие, в процессе всплытия он не меняется;
  • this – это текущий элемент, до которого дошло всплытие, на нём сейчас выполняется обработчик.
Пример

[свернуть]

Всплывают большинство событий, но есть исключения, например, событие focus не всплывает.

Прерывание всплытия

Событие "всплывает", начиная с «целевого» элемента, вверх по цепочке родительских элементов до элемента <html>, а затем до объекта document (а иногда и до window).

Для прерывания всплытия любым промежуточным обработчиком используется метод event.stopPropagation(), например:

Метод event.stopPropagation() препятствует всплытию события дальше по цепочке элементов, однако если у элемента, на котором вызывается event.stopPropagation(), есть несколько обработчиков на одно событие, то все они будут выполнены.

Метод event.stopImmediatePropagation()  не только предотвращает всплытие, но и останавливает обработку событий на текущем элементе.

Не рекомендуется прекращать всплытие без необходимости (подробнее на https://learn.javascript.ru).

Погружение (перехват) событий DOM

Обработчики, добавленные через свойство DOM-объекта, или через HTML-атрибуты, или через addEventListener(event, handler) с двумя аргументами работают только на фазах цели (target phase) и всплытия (bubbling stage).

Чтобы поймать событие на стадии погружения, нужно использовать аргумент capture метода addEventListener(event, handler):

  • если аргумент false (по умолчанию), то событие будет поймано при всплытии;
  • если аргумент true, то событие будет перехвачено при погружении.

Пример перехвата события при погружении

Обработчик срабатывает только при клике на <div> (событие onclick не распространяется на <h1>):

И еще пример (для визуалов):

[свернуть]

Читай также https://itchief.ru/javascript/events-bubbling-capturing#bubbling

Добавить комментарий

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.