Всплытие и погружение событий: stopPropagation

Что такое всплытие и погружение событий? 🌊

Когда событие происходит в DOM (например, клик по кнопке), оно проходит три фазы:

  1. Фаза погружения (Capture phase) — событие спускается от корня (window) до целевого элемента.
  2. Фаза цели (Target phase) — событие достигает элемента-источника.
  3. Фаза всплытия (Bubble phase) — событие поднимается обратно вверх по иерархии DOM.
document.querySelector('.parent').addEventListener('click', () => {
  console.log('Этот обработчик сработает на всплытии (по умолчанию)');
}, false); // `false` = всплытие (можно не указывать)

document.querySelector('.parent').addEventListener('click', () => {
  console.log('Этот обработчик сработает на погружении');
}, true); // `true` = погружение

💡 По умолчанию обработчики работают на всплытии, но с третьим аргументом true их можно переключить на погружение.


Зачем нужно останавливать всплытие? 🛑

Представьте: у вас есть кнопка внутри <div>, и оба элемента имеют обработчик клика. Если кликнуть по кнопке, событие сработает сначала на ней, а затем всплывёт на родительский <div>.

const button = document.querySelector('button');
const parent = document.querySelector('.parent');

button.addEventListener('click', () => console.log('Клик по кнопке'));
parent.addEventListener('click', () => console.log('Клик по родителю'));

Вывод в консоли:

Клик по кнопке  
Клик по родителю  

Если такое поведение нежелательно, можно остановить всплытие методом stopPropagation().


Как работает stopPropagation()? ⚡

Этот метод останавливает дальнейшее распространение события текущей фазы (всплытия или погружения).

button.addEventListener('click', (event) => {
  event.stopPropagation(); // Остановка всплытия
  console.log('Клик по кнопке (всплытие остановлено)');
});

parent.addEventListener('click', () => console.log('Клик по родителю'));

Теперь при клике на кнопку в консоли будет только:

Клик по кнопке (всплытие остановлено)  

⚠️ Важно! stopPropagation() не предотвращает другие обработчики на том же элементе — для этого есть stopImmediatePropagation().


Когда использовать stopPropagation()? 🎯

  1. Модальные окна — чтобы клик по контенту не закрывал окно через обработчик на фоне.
  2. Вложенные меню — чтобы клик по подменю не триггерил родительский обработчик.
  3. Виджеты — если компонент должен работать изолированно.

Как отличить stopPropagation от preventDefault? 🤔

Метод Что делает? Пример использования
stopPropagation() Останавливает всплытие/погружение Клик по кнопке внутри <div> не триггерит родителя
preventDefault() Отменяет стандартное поведение браузера Запрет отправки формы или перехода по ссылке

Практический пример: выпадающее меню 🍔

Допустим, у нас есть меню, которое должно закрываться при клике только вне его области.

<div class="dropdown">
  <button class="dropdown-toggle">Меню</button>
  <div class="dropdown-content">
    <a href="#">Пункт 1</a>
    <a href="#">Пункт 2</a>
  </div>
</div>
document.querySelector('.dropdown-toggle').addEventListener('click', (e) => {
  e.stopPropagation(); // Клик по кнопке не всплывёт на document
  document.querySelector('.dropdown-content').classList.toggle('visible');
});

document.addEventListener('click', () => {
  // Закрываем меню при клике в любом месте страницы
  document.querySelector('.dropdown-content').classList.remove('visible');
});

Теперь меню будет закрываться только при клике вне его области, а клик по кнопке не приведёт к немедленному закрытию.


Итог 🏁

  • Всплытие и погружение — это механизм распространения событий в DOM.
  • stopPropagation() останавливает событие на текущей фазе (но не другие обработчики на этом же элементе).
  • Используйте его, когда нужно изолировать поведение компонентов.
  • Не путайте с preventDefault() — он отменяет действие браузера, а не всплытие.

Попробуйте применить это в своих проектах — например, для создания кастомных dropdown’ов или сложных интерактивных элементов! 🔥

Скрыть рекламу навсегда

🧠 Учёба без воды и зубрёжки

Закрытый Boosty с наработками опытного преподавателя.

Объясняю сложное так, чтобы щелкнуло.

🚀 Забрать доступ к Boosty