Полное руководство по event bubbling и event capturing — кому пользаются и как правильно применять веб-разработчикам

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

Event bubbling (всплытие событий) и event capturing (захват событий) — это механизмы, используемые для обработки событий, которые происходят внутри элементов HTML. Когда событие происходит на элементе, оно может распространяться на его родительские элементы (вверх по дереву) или быть отслежено и обработано непосредственно на текущем элементе или его потомках (вниз по дереву). Это позволяет реализовать различные сценарии взаимодействия и обработки событий.

Event bubbling — это процесс, когда событие сначала обрабатывается на самом глубоко вложенном элементе, затем на его родительском элементе и так далее, постепенно переходя к самому верхнему элементу дерева. Event capturing, наоборот, начинается с верхнего элемента и проходит по дереву вниз, постепенно доходя до самого глубоко вложенного элемента.

Что такое event bubbling и event capturing

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

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

Для понимания преимуществ и использования этих концепций важно понимать моменты, когда каждая из них может быть полезна. Event bubbling предоставляет простой и удобный способ обработки событий, когда нам нужно, чтобы одно и то же событие применялось к нескольким элементам. Event capturing полезен, когда нам нужно перехватить событие на самом раннем этапе, например, для валидации или предотвращения срабатывания других обработчиков событий.

В HTML мы можем использовать атрибуты onclick и onfocus, чтобы присвоить функцию обработчика событий элементам. В JavaScript можно также использовать методы addEventListener и removeEventListener для добавления и удаления обработчиков событий.

СобытиеEvent bubblingEvent capturing
onclickОт внутренних к внешним элементамОт внешних к внутренним элементам
onfocusОт внутренних к внешним элементамОт внешних к внутренним элементам

Используя event bubbling и event capturing, разработчики могут создавать более интерактивные и динамические веб-приложения, обрабатывать события эффективным способом и управлять поведением пользовательского взаимодействия.

Event bubbling

Пример:

  • У нас есть div, внутри которого размещены несколько элементов: кнопки, ссылки, изображения и т.д.
  • Добавим обработчики событий на каждый из этих элементов.
  • Если мы нажимаем на кнопку, событие «click» срабатывает сначала на самой кнопке, а затем по мере всплытия доходит до родительских элементов (div, родитель кнопки и т.д.).

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

Как работает event bubbling

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

Таким образом, при использовании event bubbling, если у элемента и его родительского элемента есть обработчики событий, оба они будут вызваны. Это позволяет удобно обрабатывать события на нескольких элементах, находящихся внутри друг друга.

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

Event bubbling является стандартным поведением во многих браузерах и может быть полезным для работы с интерактивными элементами, такими как кнопки, ссылки и списки. Однако в некоторых ситуациях может потребоваться использование event capturing, обработка событий в обратном порядке, когда событие сначала поймано на самом верхнем элементе, а затем передаётся по стеку ниже.

Event capturing

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

Для использования event capturing в JavaScript, вы можете использовать метод addEventListener и передать третий аргумент со значением true. Например:


document.getElementById('myElement').addEventListener('click', myFunction, true);

В данном примере, обработчик события myFunction будет вызван на элементе с id 'myElement' перед тем, как событие будет передано ниже по иерархии элементов.

Как работает event capturing

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

Для примера, предположим, что у нас есть HTML-элемент A, который содержит HTML-элемент B, а затем сам элемент B содержит HTML-элемент C. Если мы назначим обработчик события для элемента C и произойдет событие на этом элементе, то в случае использования event capturing обработчики будут вызываться в следующем порядке: A, затем B, затем C.

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

Разница между event bubbling и event capturing

При использовании event bubbling, событие сначала обрабатывается на самом вложенном элементе, затем на его родительском элементе и так далее, пока не достигнет самого верхнего элемента в DOM дереве. Это означает, что событие «всплывает» от вложенного элемента к его родителям.

При использовании event capturing, событие происходит в обратном порядке: оно сначала обрабатывается на самом верхнем элементе и затем «спускается» по иерархии DOM дерева до самого вложенного элемента.

Разница между этими двумя механизмами состоит в порядке, в котором обрабатываются события. Event bubbling — это наиболее распространенный вариант и по умолчанию используется в большинстве браузеров. Event capturing может быть использован явно, задавая значение «true» для метода addEventListener.

Использование event bubbling или event capturing полностью зависит от конкретной ситуации и требований приложения. В большинстве случаев event bubbling является предпочтительным вариантом, так как обработчики событий могут быть легче добавлены и удалены с помощью метода addEventListener. Однако event capturing может быть полезным при необходимости предотвратить всплывание событий или контролировать порядок их обработки.

Когда использовать event bubbling и event capturing

В зависимости от ситуации, вы можете выбрать, нужно ли использовать event bubbling или event capturing в вашем коде. Рассмотрим несколько сценариев, когда каждый из этих методов может быть полезным.

Event bubbling может быть полезен в следующих ситуациях:

  • Обработка событий вложенных элементов: Если у вас есть группа элементов вложенных друг в друга, и вы хотите, чтобы событие было обработано на каждом из этих элементов по отдельности, то event bubbling может быть полезным. Например, при клике на вложенные кнопки внутри списка, вы можете использовать event bubbling, чтобы обрабатывать клики на каждой кнопке независимо.
  • Управление состоянием родительского элемента: Если у вас есть родительский элемент, который должен отреагировать на события, происходящие внутри дочерних элементов, event bubbling может быть полезным для упрощения кода. Например, если вы имеете список дел с чекбоксами, вы можете использовать event bubbling для отметки элемента списка, когда его чекбокс изменяется.

Event capturing может быть полезен при следующих сценариях:

  • Остановка события на самом раннем этапе: Если вам нужно предотвратить распространение события на более глубокие элементы, event capturing может быть полезным. Например, если вы хотите, чтобы щелчок на кнопке не запускал обработчик для ее родительского элемента, вы можете использовать event capturing, чтобы перехватить событие до достижения кнопки.
  • Манипуляция событием до его обработки: Если вы хотите изменить или проверить событие до его обработки обычными обработчиками, event capturing дает вам возможность сделать это. Например, вы можете использовать event capturing для проверки прав доступа пользователя перед выполнением определенного действия.

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

Примеры использования event bubbling и event capturing

Рассмотрим пример использования event bubbling:

HTMLJavaScript
<div id="parent">
<div id="child">
<button id="button">Нажми меня</button>
</div>
</div>
const parent = document.querySelector('#parent');
const child = document.querySelector('#child');
const button = document.querySelector('#button');
parent.addEventListener('click', () => {
console.log('Родительский элемент');
});
child.addEventListener('click', () => {
console.log('Дочерний элемент');
});
button.addEventListener('click', () => {
console.log('Кнопка');
});

При клике на кнопку «Нажми меня» будет выполнена следующая последовательность обработчиков:

  1. Обработчик кнопки
  2. Обработчик дочернего элемента
  3. Обработчик родительского элемента

Рассмотрим пример использования event capturing:

HTMLJavaScript
<div id="parent">
<div id="child">
<button id="button">Нажми меня</button>
</div>
</div>
const parent = document.querySelector('#parent');
const child = document.querySelector('#child');
const button = document.querySelector('#button');
parent.addEventListener('click', () => {
console.log('Родительский элемент', { capture: true });
}, true);
child.addEventListener('click', () => {
console.log('Дочерний элемент', { capture: true });
}, true);
button.addEventListener('click', () => {
console.log('Кнопка', { capture: true });
}, true);

При клике на кнопку «Нажми меня» будет выполнена следующая последовательность обработчиков:

  1. Обработчик родительского элемента
  2. Обработчик дочернего элемента
  3. Обработчик кнопки

Пример использования event bubbling:

Давайте представим ситуацию, в которой у нас есть несколько вложенных элементов на веб-странице:

HTMLJavaScript

<div id="outer">
<p>Внешний элемент</p>
<div id="middle">
<p>Средний элемент</p>
<div id="inner">
<p>Внутренний элемент</p>
</div>
</div>
</div>


const outer = document.getElementById('outer');
const middle = document.getElementById('middle');
const inner = document.getElementById('inner');
outer.addEventListener('click', () => {
console.log('Внешний элемент');
});
middle.addEventListener('click', () => {
console.log('Средний элемент');
});
inner.addEventListener('click', () => {
console.log('Внутренний элемент');
});

Если мы кликаем на внутренний элемент, то в консоли будет выведено:


Пример использования event capturing

Для использования event capturing в JavaScript можно задать третий параметр в функции addEventListener или использовать метод addEventListener с параметром true. Например:

element.addEventListener('click', myFunction, true); element.addEventListener('click', myFunction, { capture: true });

При использовании event capturing обработчик события сначала выполнится на самом внешнем элементе в иерархии и затем будет передаваться по цепочке внутрь. То есть, событие будет перехвачено на самом верхнем элементе и последовательно передано внутрь каждого родительского элемента до целевого элемента, на котором произошло событие.

Пример использования event capturing:

<div id="container">
<div id="parent">
<div id="child">Нажми меня!</div>
</div>
</div>

Следующий JavaScript-код добавит обработчик события с использованием event capturing:

const container = document.querySelector('#container');
const parent = document.querySelector('#parent');
const child = document.querySelector('#child');
container.addEventListener('click', function() {
console.log('Event capturing: container');
}, true);
parent.addEventListener('click', function() {
console.log('Event capturing: parent');
}, true);
child.addEventListener('click', function() {
console.log('Event capturing: child');
}, true);

При клике на элемент с id "child" в консоль будет выведено:

Event capturing: container
Event capturing: parent
Event capturing: child

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

Оцените статью
Добавить комментарий