← Назад к вопросам

Как отловить событие на погружение?

2.0 Middle🔥 141 комментариев
#Soft Skills и рабочие процессы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Event Bubbling и фаза погружения (Capturing Phase)

Вопрос о погружении относится к фазам распространения событий в DOM. В браузере события проходят три фазы: погружение (capturing), цель (target) и всплытие (bubbling).

Три фазы события

Когда вы кликаете на элемент, событие проходит три этапа:

1. CAPTURING PHASE (погружение) — событие идёт вниз от window к целевому элементу
2. TARGET PHASE (целевая фаза) — событие на самом элементе
3. BUBBLING PHASE (всплытие) — событие идёт вверх от элемента к window

По умолчанию обработчики вешаются на фазу всплытия (bubbling).

Отловить событие на погружение (Capturing)

Для перехвата события в фазе погружения используй третий параметр в addEventListener:

// Запуск на фазе всплытия (по умолчанию)
element.addEventListener("click", handler); // bubbling phase
element.addEventListener("click", handler, false); // явно bubbling

// Запуск на фазе погружения
element.addEventListener("click", handler, true); // capturing phase
element.addEventListener("click", handler, { capture: true }); // объект опций

Практический пример

const parent = document.getElementById("parent");
const child = document.getElementById("child");

// Фаза погружения - срабатывает ПЕРВОЙ
parent.addEventListener("click", (e) => {
  console.log("Родитель - ПОГРУЖЕНИЕ (capturing)");
}, true); // true = capturing

// Фаза всплытия - срабатывает ВТОРОЙ
parent.addEventListener("click", (e) => {
  console.log("Родитель - ВСПЛЫТИЕ (bubbling)");
}, false); // false = bubbling (по умолчанию)

// Клик на child
child.addEventListener("click", (e) => {
  console.log("Ребёнок - нажата");
});

// HTML:
// <div id="parent">
//   <div id="child">Click me</div>
// </div>

// Вывод при клике на child:
// 1. Родитель - ПОГРУЖЕНИЕ (capturing)
// 2. Ребёнок - нажата
// 3. Родитель - ВСПЛЫТИЕ (bubbling)

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

Фаза погружения полезна, когда нужно перехватить событие ДО того, как оно достигнет целевого элемента:

// Пример 1: Глобальный обработчик на document с capturing
document.addEventListener("click", (e) => {
  console.log("Клик произошёл на:", e.target);
}, true); // capturing - срабатывает для всех кликов в документе

// Пример 2: Перехват события перед обработкой
const form = document.getElementById("form");
form.addEventListener("submit", (e) => {
  console.log("Форма отправляется (capturing)");
  // Можно отменить распространение
  e.stopPropagation();
}, true);

// Внутри формы есть input, и его обработчик не сработает
const input = document.getElementById("input");
input.addEventListener("submit", () => {
  console.log("Это не сработает из-за stopPropagation");
});

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

// HTML
// <div id="outer">
//   <div id="inner">
//     <button id="btn">Click</button>
//   </div>
// </div>

const outer = document.getElementById("outer");
const inner = document.getElementById("inner");
const btn = document.getElementById("btn");

// --- BUBBLING PHASE (по умолчанию) ---
// Порядок: btn -> inner -> outer

btn.addEventListener("click", () => console.log("btn - bubble"));
inner.addEventListener("click", () => console.log("inner - bubble"));
outer.addEventListener("click", () => console.log("outer - bubble"));

// Вывод: btn - bubble, inner - bubble, outer - bubble

// --- CAPTURING PHASE ---
// Порядок: outer -> inner -> btn

btn.addEventListener("click", () => console.log("btn - capture"), true);
inner.addEventListener("click", () => console.log("inner - capture"), true);
outer.addEventListener("click", () => console.log("outer - capture"), true);

// Вывод: outer - capture, inner - capture, btn - capture

Остановка распространения

Чтобы остановить распространение события на других фазах:

element.addEventListener("click", (event) => {
  // Остановить распространение
  event.stopPropagation(); // событие не пойдёт выше

  // Остановить все обработчики для этого события
  event.stopImmediatePropagation();

  // Отменить действие по умолчанию (например, переход по ссылке)
  event.preventDefault();
});

React и фазы событий

В React используется система делегирования, события вешаются на корневой элемент. Для capturing в React нужно использовать нативные события:

function Component() {
  useEffect(() => {
    // React обработчики используют bubbling
    const handleClick = () => console.log("Bubbling");
    element.addEventListener("click", handleClick); // bubbling

    // Для capturing нужен нативный addEventListener
    element.addEventListener("click", handleClick, { capture: true });

    return () => {
      element.removeEventListener("click", handleClick);
      element.removeEventListener("click", handleClick, { capture: true });
    };
  }, []);

  return <div ref={ref}>Content</div>;
}

Итого

Для отловки события на погружение (capturing phase):

  1. Используй третий параметр — addEventListener(event, handler, true) или { capture: true }
  2. Фаза погружения срабатывает первой — от родителя к элементу
  3. Фаза всплытия срабатывает второй — от элемента к родителю
  4. stopPropagation() останавливает распространение события
  5. В React используй нативный addEventListener для capturing

Capturing используется редко, обычно работают со всплытием (bubbling).

Как отловить событие на погружение? | PrepBro