DOM и события: всплытие, погружение, делегирование

↑ 1.4 JavaScript: основы · ← Предыдущая · → Следующая

Желательно~3 мин чтенияУровень: junior

Зачем это на собесе

Фазы событий и делегирование — стабильный вопрос; во фреймворках понимание помогает отлаживать поведение.

Объяснение

DOM — древовидная модель документа, доступная из JS.

const el = document.querySelector(".card");
document.querySelectorAll("li");        // статический NodeList
el.classList.toggle("active");
el.dataset.id;                          // data-id
el.textContent = "текст";               // безопасно (innerHTML — риск XSS)
const node = document.createElement("li"); list.append(node);
el.closest(".list"); el.matches(".x");
el.getBoundingClientRect();

Фазы события: погружение (capturing: от window вниз) → цель (target) → всплытие (bubbling: вверх). Слушатель по умолчанию срабатывает на всплытии.

list.addEventListener("click", (e) => {
  const item = e.target.closest("[data-id]");        // делегирование: один обработчик на список
  if (!item || !list.contains(item)) return;
  select(item.dataset.id);
});
btn.addEventListener("click", handler, { once: true, passive: true });
form.addEventListener("submit", (e) => { e.preventDefault(); });
e.stopPropagation();   // остановить всплытие; stopImmediatePropagation — и другие слушатели
СвойствоСмысл
event.targetэлемент, где произошло событие
event.currentTargetэлемент с обработчиком
preventDefault()отменить действие по умолчанию
passive: trueобещание не вызывать preventDefault (плавный скролл)
capture: trueслушать на погружении

Делегирование: один обработчик на родителе вместо множества на потомках — экономия памяти, работает для динамически добавленных элементов.

Иные важные события: DOMContentLoaded, load, input, change, focus/blur (не всплывают; focusin/out всплывают), scroll, resize, IntersectionObserver, MutationObserver, ResizeObserver, CustomEvent.

Нюансы и подводные камни

  • Не забывайте снимать слушатели (removeEventListener, AbortController) — утечки.
  • Массовые обновления DOM в цикле вызывают layout: собирайте в DocumentFragment, группируйте чтение и запись.
  • stopPropagation ломает делегирование и аналитику — используйте осознанно.
  • innerHTML с пользовательскими данными — XSS.
  • Обработчики scroll/resize — с throttle или через Observers.

Практика

  1. Реализуйте делегирование для списка с динамическими элементами.
  2. Воспроизведите всплытие и погружение, выведя порядок вызовов.
  3. Подгрузите данные при прокрутке через IntersectionObserver.

Вопросы с ответами

Связанные темы