В каком порядке сработают обработчики клика на div с вложенной кнопкой
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Порядок срабатывания обработчиков клика на вложенные элементы
Фаза события определяет порядок срабатывания обработчиков. Когда вы кликаете на вложенный элемент, событие проходит три фазы: захват (capturing), целевую фазу (target) и всплытие (bubbling).
Три фазы события
При клике на кнопку, вложенную в div:
<div id="outer">
<button id="btn">Нажми меня</button>
</div>
Порядок выполнения:
- Фаза захвата (Capturing) - событие идет сверху вниз: window -> document -> html -> body -> div -> button
- Целевая фаза (Target) - событие достигает самого элемента (button)
- Фаза всплытия (Bubbling) - событие идет снизу вверх: button -> div -> body -> html -> document -> window
Практический пример
const outer = document.getElementById('outer');
const btn = document.getElementById('btn');
// Обработчик на div - фаза всплытия (по умолчанию)
outer.addEventListener('click', () => {
console.log('1. DIV - всплытие');
});
// Обработчик на div - фаза захвата
outer.addEventListener('click', () => {
console.log('2. DIV - захват');
}, true);
// Обработчик на кнопку
btn.addEventListener('click', () => {
console.log('3. BTN - целевая фаза');
});
Результат в консоли:
2. DIV - захват
3. BTN - целевая фаза
1. DIV - всплытие
Порядок по умолчанию (фаза всплытия)
Если вы не указываете третий параметр addEventListener, происходит всплытие:
const parent = document.getElementById('parent');
const child = document.getElementById('child');
parent.addEventListener('click', () => {
console.log('Клик на parent (всплытие)');
});
child.addEventListener('click', () => {
console.log('Клик на child');
});
// При клике на child выведет:
// 'Клик на child'
// 'Клик на parent (всплытие)'
Контроль фаз
// Фаза всплытия (useCapture = false, по умолчанию)
element.addEventListener('click', handler, false);
// Фаза захвата (useCapture = true)
element.addEventListener('click', handler, true);
Остановка распространения события
stopPropagation() - останавливает распространение события (не будет всплытия/захвата на родителей):
button.addEventListener('click', (event) => {
event.stopPropagation();
console.log('Клик на кнопку');
});
div.addEventListener('click', () => {
console.log('Это никогда не выполнится');
});
stopImmediatePropagation() - останавливает и всплытие, и остальные обработчики на этом же элементе:
button.addEventListener('click', (event) => {
event.stopImmediatePropagation();
console.log('Первый обработчик');
});
button.addEventListener('click', () => {
console.log('Это не выполнится');
});
Сложный пример с несколькими уровнями
<div id="level1" class="level-1">
<div id="level2" class="level-2">
<button id="btn" class="btn">Клик</button>
</div>
</div>
document.getElementById('level1').addEventListener('click', () => {
console.log('Level 1 - всплытие');
});
document.getElementById('level2').addEventListener('click', () => {
console.log('Level 2 - всплытие');
});
document.getElementById('btn').addEventListener('click', () => {
console.log('Button - целевая фаза');
});
// При клике на кнопку:
// 'Button - целевая фаза'
// 'Level 2 - всплытие'
// 'Level 1 - всплытие'
Полный порядок фаз
Для структуры с захватом:
// Все три элемента с захватом и всплытием
level1.addEventListener('click', () => console.log('L1 захват'), true);
level2.addEventListener('click', () => console.log('L2 захват'), true);
btn.addEventListener('click', () => console.log('BTN захват'), true);
level1.addEventListener('click', () => console.log('L1 всплытие'), false);
level2.addEventListener('click', () => console.log('L2 всплытие'), false);
btn.addEventListener('click', () => console.log('BTN всплытие'), false);
// Результат:
// 'L1 захват' - фаза захвата
// 'L2 захват' - фаза захвата
// 'BTN захват' - фаза захвата
// 'BTN всплытие' - целевая фаза (всплытие)
// 'L2 всплытие' - фаза всплытия
// 'L1 всплытие' - фаза всплытия
Практический совет
В большинстве случаев используй всплытие (значение false или просто опусти параметр) - это проще и интуитивнее. Захват редко требуется, основной его сценарий - предотвращение всплытия на ранней стадии.