0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Предположим, что у нас есть несколько элементов, на каждом из которых висит обработчик события click. Один элемент внешний - div. Внутри него находятся два элемента с кнопками:</p>
1
<p>Предположим, что у нас есть несколько элементов, на каждом из которых висит обработчик события click. Один элемент внешний - div. Внутри него находятся два элемента с кнопками:</p>
2
<p>Если выполнить щелчок по области внешнего элемента, то выполнится обработчик, привязанный к этому внешнему элементу.</p>
2
<p>Если выполнить щелчок по области внешнего элемента, то выполнится обработчик, привязанный к этому внешнему элементу.</p>
3
<p>Если выполнить щелчок по внутреннему элементу, то автоматически выполнится щелчок и по внешнему элементу. Значит, отработают оба события.</p>
3
<p>Если выполнить щелчок по внутреннему элементу, то автоматически выполнится щелчок и по внешнему элементу. Значит, отработают оба события.</p>
4
<p>Возникает закономерный вопрос: "В каком порядке выполнятся эти события после щелчка на кнопку?". В общем случае событие проходит сквозь дерево от корня до самого глубокого элемента, на котором событие сработало, а затем в обратном направлении. Путешествие события туда и обратно называется его<strong>стадиями</strong>или<strong>фазами</strong>, ниже поговорим о них подробнее.</p>
4
<p>Возникает закономерный вопрос: "В каком порядке выполнятся эти события после щелчка на кнопку?". В общем случае событие проходит сквозь дерево от корня до самого глубокого элемента, на котором событие сработало, а затем в обратном направлении. Путешествие события туда и обратно называется его<strong>стадиями</strong>или<strong>фазами</strong>, ниже поговорим о них подробнее.</p>
5
<h2>Погружение (Capturing)</h2>
5
<h2>Погружение (Capturing)</h2>
6
<p>Когда событие только возникло, оно начинает двигаться по DOM-дереву от корневого узла до самого глубокого, на котором произошло событие:</p>
6
<p>Когда событие только возникло, оно начинает двигаться по DOM-дереву от корневого узла до самого глубокого, на котором произошло событие:</p>
7
<p>| | ---------------| |--------------- | div | | | | -----------| |----------- | | | button \ / | | | ------------------------- | | Event CAPTURING | ---------------------------------</p>
7
<p>| | ---------------| |--------------- | div | | | | -----------| |----------- | | | button \ / | | | ------------------------- | | Event CAPTURING | ---------------------------------</p>
8
<p>Попутно на стадии погружения будут выполнены обработчики, которые были привязаны к этой стадии. Привязка регулируется третьим параметром функции addEventListener:</p>
8
<p>Попутно на стадии погружения будут выполнены обработчики, которые были привязаны к этой стадии. Привязка регулируется третьим параметром функции addEventListener:</p>
9
<p>В примере выше пользователь кликнул по кнопке Send, которая находится внутри элемента div. Значение true привязывает обработчики к стадии погружения. Событие срабатывает вниз по дереву от корневого узла. Корневым узлом является div, срабатывает обработчик этого события на этом элементе. Затем событие переходит дальше к дочернему элементу, на котором произошло событие и вызывается обработчик события этого элемента. В нашем случае это кнопка Send. Получится такой вывод:</p>
9
<p>В примере выше пользователь кликнул по кнопке Send, которая находится внутри элемента div. Значение true привязывает обработчики к стадии погружения. Событие срабатывает вниз по дереву от корневого узла. Корневым узлом является div, срабатывает обработчик этого события на этом элементе. Затем событие переходит дальше к дочернему элементу, на котором произошло событие и вызывается обработчик события этого элемента. В нашем случае это кнопка Send. Получится такой вывод:</p>
10
<p>Div alert Button Send alert</p>
10
<p>Div alert Button Send alert</p>
11
<p>Обратите внимание, что обработчик кнопки Cancel не был вызван, так как событие произошло не на этой кнопке.</p>
11
<p>Обратите внимание, что обработчик кнопки Cancel не был вызван, так как событие произошло не на этой кнопке.</p>
12
<p><a>https://codepen.io/hexlet/pen/KKbmQMv</a></p>
12
<p><a>https://codepen.io/hexlet/pen/KKbmQMv</a></p>
13
<h2>Всплытие (Bubbling)</h2>
13
<h2>Всплытие (Bubbling)</h2>
14
<p>После остановки погружения на элементе target, начинается всплытие:</p>
14
<p>После остановки погружения на элементе target, начинается всплытие:</p>
15
<p>/ \ ---------------| |--------------- | div | | | | -----------| |----------- | | | button | | | | | ------------------------- | | Event BUBBLING | ---------------------------------</p>
15
<p>/ \ ---------------| |--------------- | div | | | | -----------| |----------- | | | button | | | | | ------------------------- | | Event BUBBLING | ---------------------------------</p>
16
<p>Именно эта стадия подразумевается при вызове addEventListener без третьего параметра:</p>
16
<p>Именно эта стадия подразумевается при вызове addEventListener без третьего параметра:</p>
17
<p>На ней выполнение обработчиков происходит изнутри наружу, поэтому порядок вывода сообщений меняется:</p>
17
<p>На ней выполнение обработчиков происходит изнутри наружу, поэтому порядок вывода сообщений меняется:</p>
18
<p><a>https://codepen.io/hexlet/pen/QWzvQKv</a></p>
18
<p><a>https://codepen.io/hexlet/pen/QWzvQKv</a></p>
19
<p>Всплытие событий - это важная часть поведения DOM. Без него было бы невозможно реализовать события, которые срабатывают на целых блоках, а не только самых глубоких элементах. Самый простой пример - контекстное меню.</p>
19
<p>Всплытие событий - это важная часть поведения DOM. Без него было бы невозможно реализовать события, которые срабатывают на целых блоках, а не только самых глубоких элементах. Самый простой пример - контекстное меню.</p>
20
<p>Когда пользователь кликает правой кнопкой мыши, браузер генерирует событие contextmenu. Это событие можно перехватить с помощью JavaScript, чтобы:</p>
20
<p>Когда пользователь кликает правой кнопкой мыши, браузер генерирует событие contextmenu. Это событие можно перехватить с помощью JavaScript, чтобы:</p>
21
<ul><li>Показать своё контекстное меню (вместо стандартного).</li>
21
<ul><li>Показать своё контекстное меню (вместо стандартного).</li>
22
<li>Отменить стандартное поведение (event.preventDefault()).</li>
22
<li>Отменить стандартное поведение (event.preventDefault()).</li>
23
<li>Сделать меню более контекстным (например, разное для разных участков страницы).</li>
23
<li>Сделать меню более контекстным (например, разное для разных участков страницы).</li>
24
</ul><p><a>https://codepen.io/hexlet/pen/myyozNo</a></p>
24
</ul><p><a>https://codepen.io/hexlet/pen/myyozNo</a></p>
25
<p>Другой пример - таблицы, устроенные по принципу Excel. Эти таблицы огромны. Добавление событий на каждую ячейку привело бы к созданию большого числа одинаковых обработчиков, которые нужно постоянно добавлять с ростом таблицы. Кроме дополнительного кода, такая схема еще и тормозит на больших объемах. Гораздо проще повесить один обработчик на всю таблицу. В примере ниже добавлен обработчик клика на таблицу. При этом он будет срабатывать при нажатии на любую из кнопок, которые находятся внутри таблицы.</p>
25
<p>Другой пример - таблицы, устроенные по принципу Excel. Эти таблицы огромны. Добавление событий на каждую ячейку привело бы к созданию большого числа одинаковых обработчиков, которые нужно постоянно добавлять с ростом таблицы. Кроме дополнительного кода, такая схема еще и тормозит на больших объемах. Гораздо проще повесить один обработчик на всю таблицу. В примере ниже добавлен обработчик клика на таблицу. При этом он будет срабатывать при нажатии на любую из кнопок, которые находятся внутри таблицы.</p>
26
<p><a>https://codepen.io/hexlet/pen/PoXKYor</a></p>
26
<p><a>https://codepen.io/hexlet/pen/PoXKYor</a></p>
27
<h2>W3C Модель</h2>
27
<h2>W3C Модель</h2>
28
<p>Большинство событий проходят обе стадии, сначала погружаясь в глубину дерева и затем поднимаясь до самого верха. Стадия погружения используется редко, большая часть обработчиков вешается на стадию всплытия.</p>
28
<p>Большинство событий проходят обе стадии, сначала погружаясь в глубину дерева и затем поднимаясь до самого верха. Стадия погружения используется редко, большая часть обработчиков вешается на стадию всплытия.</p>
29
<p>В предыдущем уроке мы познакомились с объектом e.target. Это самый глубокий элемент, до которого идет погружение. В процессе всплытия target не меняется. Благодаря ему всегда можно узнать, где конкретно произошло событие.</p>
29
<p>В предыдущем уроке мы познакомились с объектом e.target. Это самый глубокий элемент, до которого идет погружение. В процессе всплытия target не меняется. Благодаря ему всегда можно узнать, где конкретно произошло событие.</p>
30
<p>Кроме него, доступен объект currentTarget - это элемент, к которому прикреплен данный обработчик. В зависимости от ситуации используется тот или иной:</p>
30
<p>Кроме него, доступен объект currentTarget - это элемент, к которому прикреплен данный обработчик. В зависимости от ситуации используется тот или иной:</p>
31
<p>В обычной ситуации событие должно всплывать до конца, но иногда могут возникать ситуации, когда всплытие нежелательно.</p>
31
<p>В обычной ситуации событие должно всплывать до конца, но иногда могут возникать ситуации, когда всплытие нежелательно.</p>
32
<p>Можно его остановить двумя способами:</p>
32
<p>Можно его остановить двумя способами:</p>
33
<ul><li>event.stopPropagation() - останавливает всплытие, но позволяет доработать всем обработчикам, которые висят на текущем элементе</li>
33
<ul><li>event.stopPropagation() - останавливает всплытие, но позволяет доработать всем обработчикам, которые висят на текущем элементе</li>
34
<li>event.stopImmediatePropagation() - останавливает всплытие вместе со всеми обработчиками</li>
34
<li>event.stopImmediatePropagation() - останавливает всплытие вместе со всеми обработчиками</li>
35
</ul><p>Подведем итог. Перехват - это механизм передачи события обработчику. При погружении или всплытии событие переходит от одного элемента другому. Если в элементе есть обработчик этого события, то он вызывается - происходит перехват события обработчиком. Используя описанные выше методы, мы можем остановить процесс передачи события между элементами.</p>
35
</ul><p>Подведем итог. Перехват - это механизм передачи события обработчику. При погружении или всплытии событие переходит от одного элемента другому. Если в элементе есть обработчик этого события, то он вызывается - происходит перехват события обработчиком. Используя описанные выше методы, мы можем остановить процесс передачи события между элементами.</p>