Предположим, что у нас есть два вложенных элемента, на каждом из которых висит обработчик события click. Если выполнить щелчок по области внешнего элемента, не затрагивающей внутренний, то выполнится обработчик, привязанный к этому внешнему элементу. Если выполнить щелчок по внутреннему элементу, автоматически выполнится щелчок и по внешнему, а значит, отработают оба события.
<div>
<button>Send</button>
</div>
button.addEventListener('click', () => alert('Boom 1!'));
div.addEventListener('click', () => alert('Boom 2!'));
Возникает закономерный вопрос, в каком порядке выполнятся эти события после щелчка на кнопку? В общем случае событие проходит сквозь дерево, начиная от корня до самого глубокого элемента, на котором событие сработало, и затем в обратном направлении. Путешествие события туда и обратно называется его стадиями или фазами, ниже о них подробнее.
Когда событие только возникло, оно начинает двигаться по 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!
После остановки погружения на target элементе, начинается всплытие.
/ \
---------------| |---------------
| div | | |
| -----------| |----------- |
| | button | | | |
| ------------------------- |
| Event BUBBLING |
---------------------------------
Именно эта стадия подразумевается при вызове addEventListener
без указания третьего параметра.
button.addEventListener('click', () => alert('Boom 1!'));
div.addEventListener('click', () => alert('Boom 2!'));
На ней выполнение обработчиков происходит изнутри наружу:
Boom 1!
Boom 2!
Согласно стандарту, большинство событий проходят обе стадии, сначала погружаясь в глубину дерева и затем поднимаясь до самого верха. Стадия погружения при этом используется крайне редко, большая часть обработчиков вешается на стадию всплытия.
В предыдущем уроке мы познакомились с объектом e.target
. Это самый глубокий элемент, до которого идет погружение. Target не меняется в процессе всплытия. Благодаря ему всегда можно узнать, где конкретно произошло событие. Кроме него, доступен объект currentTarget
- это элемент, к которому прикреплен данный обработчик. В зависимости от ситуации используется тот или иной.
В обычной ситуации событие должно всплывать до конца, но иногда могут возникать ситуации, когда всплытие нежелательно.
Сделать это можно двумя способами:
event.stopPropagation()
event.stopImmediatePropagation()
Первый останавливает всплытие, но дает возможность доработать всем обработчикам, которые висят на текущем элементе, второй же, не дает выполниться больше ни одному обработчику.
Вам ответят команда поддержки Хекслета или другие студенты.
Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.
Загляните в раздел «Обсуждение»:
Профессиональная подписка откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.
Наши выпускники работают в компаниях:
Зарегистрируйтесь или войдите в свой аккаунт