JS: DOM API

Перехват и всплытие

Предположим, что у нас есть два вложенных элемента, на каждом из которых висит обработчик события click. Если выполнить щелчок по области внешнего элемента, не затрагивающей внутренний, то выполнится обработчик, привязанный к этому внешнему элементу. Если выполнить щелчок по внутреннему элементу, автоматически выполнится щелчок и по внешнему, а значит, отработают оба события.

<div>
  <button>Send</button>
</div>
button.addEventListener('click', () => alert('Boom 1!'));
div.addEventListener('click', () => alert('Boom 2!'));

Возникает закономерный вопрос, в каком порядке выполнятся эти события после щелчка на кнопку? В общем случае событие проходит сквозь дерево, начиная от корня до самого глубокого элемента, на котором событие сработало, и затем в обратном направлении. Путешествие события туда и обратно называется его стадиями или фазами, ниже о них подробнее.

Погружение (Capturing)

Когда событие только возникло, оно начинает двигаться по DOM-дереву, начиная от корневого узла, до самого глубокого, на котором произошло событие.

               | |
---------------| |---------------
| div          | |              |
|   -----------| |-----------   |
|   | button   \ /          |   |
|   -------------------------   |
|        Event CAPTURING        |
---------------------------------

Попутно на стадии погружения будут выполнены обработчики, которые были привязаны к этой стадии. Привязка регулируется третьим параметром функции addEventListener.

button.addEventListener('click', () => alert('Boom 1!'), true);
div.addEventListener('click', () => alert('Boom 2!'), true);

Значение true привязывает обработчики к стадии погружения. Получится такой вывод:

Boom 2!
Boom 1!

Всплытие (Bubbling)

После остановки погружения на target элементе, начинается всплытие.

               / \
---------------| |---------------
| div          | |              |
|   -----------| |-----------   |
|   | button   | |          |   |
|   -------------------------   |
|        Event BUBBLING         |
---------------------------------

Именно эта стадия подразумевается при вызове addEventListener без указания третьего параметра.

button.addEventListener('click', () => alert('Boom 1!'));
div.addEventListener('click', () => alert('Boom 2!'));

На ней выполнение обработчиков происходит изнутри наружу:

Boom 1!
Boom 2!

W3C Модель

Согласно стандарту, большинство событий проходят обе стадии, сначала погружаясь в глубину дерева и затем поднимаясь до самого верха. Стадия погружения при этом используется крайне редко, большая часть обработчиков вешается на стадию всплытия.

В предыдущем уроке мы познакомились с объектом e.target. Это самый глубокий элемент, до которого идет погружение. Target не меняется в процессе всплытия. Благодаря ему всегда можно узнать, где конкретно произошло событие. Кроме него, доступен объект currentTarget - это элемент, к которому прикреплен данный обработчик. В зависимости от ситуации используется тот или иной.

Event Stages

В обычной ситуации событие должно всплывать до конца, но иногда могут возникать ситуации, когда всплытие нежелательно.

Сделать это можно двумя способами:

  • event.stopPropagation()
  • event.stopImmediatePropagation()

Первый останавливает всплытие, но дает возможность доработать всем обработчикам, которые висят на текущем элементе, второй же не дает выполниться больше ни одному обработчику.


<span class="translation_missing" title="translation missing: ru.web.courses.lessons.mentors.mentor_avatars">Mentor Avatars</span>

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете

Для полного доступа к курсу нужна профессиональная подписка

Профессиональная подписка откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
115
курсов
892
упражнения
2241
час теории
3196
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 115 курсов, 2000+ часов теории
  • 800 практических заданий в браузере
  • 250 000 студентов

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг».

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Rambler
Логотип компании Bookmate
Логотип компании Botmother

Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Профессия

Фронтенд-программист

Разработка фронтенд-компонентов веб-приложений
25 мая 8 месяцев

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг».