← Назад к вопросам
Как отловить событие на стадии погружения?
1.3 Junior🔥 201 комментариев
#JavaScript Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как отловить событие на стадии погружения (Capturing)
События в DOM проходят три стадии: погружение (capturing), цель (target), всплытие (bubbling). Чтобы отловить событие на стадии погружения, нужно использовать третий параметр addEventListener() или свойство capture в опциях.
Три стадии события
Когда пользователь кликает на элемент, событие проходит 3 фазы:
Window
↓ (1. CAPTURING — погружение вниз)
Document
↓
Body
↓
Div#container
↓
Button (2. TARGET — достижение цели)
↑ (3. BUBBLING — всплытие вверх)
Div#container
↑
Body
↑
Document
↑
Window
Синтаксис addEventListener
// Синтаксис
element.addEventListener(event, callback, useCapture);
// useCapture = true → слушаем на стадии CAPTURING (погружение)
// useCapture = false → слушаем на стадии BUBBLING (всплытие) — ПО УМОЛЧАНИЮ
Пример 1: Базовое использование
<div id="container">
<button id="btn">Click me</button>
</div>
const container = document.getElementById('container');
const btn = document.getElementById('btn');
// Слушаем ВСПЛЫТИЕ (обычный режим)
container.addEventListener('click', () => {
console.log('Container: BUBBLING');
}, false); // false — это по умолчанию
// Слушаем ПОГРУЖЕНИЕ
container.addEventListener('click', () => {
console.log('Container: CAPTURING');
}, true); // true — активируем режим capturing
btn.addEventListener('click', () => {
console.log('Button: TARGET');
});
// При клике на кнопку:
// Container: CAPTURING (первым!)
// Button: TARGET
// Container: BUBBLING (потом)
Объект с опциями (современный подход)
// Вместо булева значения можно использовать объект
container.addEventListener('click', handler, {
capture: true, // Погружение или всплытие
once: true, // Срабатывает только один раз
passive: false // Может ли handler вызвать preventDefault()
});
// Или с несколькими опциями
window.addEventListener('scroll', handleScroll, {
passive: true, // Улучшает производительность скролла
capture: false
});
Пример 2: Практический случай использования
Задача: Отловить событие до того, как оно достигнет целевого элемента
<div id="parent" style="border: 2px solid blue; padding: 20px;">
<input id="input" type="text" placeholder="Введи текст" />
</div>
const parent = document.getElementById('parent');
const input = document.getElementById('input');
// На стадии CAPTURING: можем остановить распространение
parent.addEventListener('focus', (e) => {
console.log('CAPTURING: Элемент получил фокус');
// Можем отменить действие ДО достижения цели
if (e.target.value === '') {
console.log('Пусто — останавливаем распространение');
e.stopPropagation();
}
}, true); // true = capturing
// На стадии TARGET
input.addEventListener('focus', (e) => {
console.log('TARGET: Инпут получил фокус');
});
// На стадии BUBBLING
parent.addEventListener('focus', (e) => {
console.log('BUBBLING: Фокус всплыл вверх');
}, false);
Пример 3: Делегирование с capturing
Делегирование событий работает с обеими фазами:
<ul id="list">
<li><button class="delete">Удалить</button></li>
<li><button class="delete">Удалить</button></li>
<li><button class="delete">Удалить</button></li>
</ul>
const list = document.getElementById('list');
// Обычный способ (всплытие)
list.addEventListener('click', (e) => {
if (e.target.classList.contains('delete')) {
console.log('Удаляем элемент (BUBBLING)');
}
}, false);
// С погружением
list.addEventListener('click', (e) => {
if (e.target.classList.contains('delete')) {
console.log('Удаляем элемент (CAPTURING)');
e.stopPropagation(); // Может помешать другим обработчикам!
}
}, true);
Пример 4: stopPropagation и stopImmediatePropagation
const container = document.getElementById('container');
const btn = document.getElementById('btn');
// CAPTURING
container.addEventListener('click', (e) => {
console.log('1. Container CAPTURING');
// e.stopPropagation(); // Остановит погружение вниз
}, true);
// TARGET — первый обработчик
btn.addEventListener('click', (e) => {
console.log('2. Button - первый обработчик');
e.stopPropagation(); // Остановит всплытие!
});
// TARGET — второй обработчик
btn.addEventListener('click', (e) => {
console.log('3. Button - второй обработчик');
});
// BUBBLING
container.addEventListener('click', (e) => {
console.log('4. Container BUBBLING');
}, false);
// При клике: 1 → 2 → 3 (4 не произойдёт из-за stopPropagation)
Таблица фаз события
| Фаза | Название | Параметр | Пример |
|---|---|---|---|
| 1 | Capturing (погружение) | true | От Window к элементу |
| 2 | Target (цель) | target phase | На самом элементе |
| 3 | Bubbling (всплытие) | false | От элемента к Window |
Частые ошибки
❌ Ошибка 1: Забывают про третий параметр
// Это ВСПЛЫТИЕ, не ПОГРУЖЕНИЕ!
element.addEventListener('click', handler);
// Правильно для ПОГРУЖЕНИЯ:
element.addEventListener('click', handler, true);
❌ Ошибка 2: Используют stopPropagation без необходимости
// Это может сломать делегирование!
element.addEventListener('click', (e) => {
e.stopPropagation(); // Осторожно!
});
❌ Ошибка 3: Путают event.target и event.currentTarget
container.addEventListener('click', (e) => {
console.log(e.target); // Элемент, на который кликнули
console.log(e.currentTarget); // Container (текущий слушатель)
}, true);
Когда использовать capturing
✅ Используй capturing когда:
- Нужно перехватить событие ДО целевого элемента
- Хочешь отменить действие на ранней стадии
- Реализуешь сложное управление фокусом
❌ Избегай capturing когда:
- Можно решить проблему через всплытие
- Есть риск сломать делегирование других обработчиков
- Нужна простота и читаемость
В 95% случаев хватает всплытия. Capturing — специальный инструмент для редких сценариев!