Всплытие и погружение событий: stopPropagation
Что такое всплытие и погружение событий? 🌊
Когда событие происходит в DOM (например, клик по кнопке), оно проходит три фазы:
- Фаза погружения (Capture phase) — событие спускается от корня (
window) до целевого элемента. - Фаза цели (Target phase) — событие достигает элемента-источника.
- Фаза всплытия (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()? 🎯
- Модальные окна — чтобы клик по контенту не закрывал окно через обработчик на фоне.
- Вложенные меню — чтобы клик по подменю не триггерил родительский обработчик.
- Виджеты — если компонент должен работать изолированно.
Как отличить 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’ов или сложных интерактивных элементов! 🔥