\n```\n\n## Практический пример\n\n```html\n
\n
\n \n \n \n
\n
\n\n\n```\n\n## Остановка всплытия (stopPropagation)\n\nМожно остановить всплытие события:\n\n```javascript\nconst child = document.getElementById('child');\nconst parent = document.getElementById('parent');\n\nchild.addEventListener('click', (e) => {\n console.log('Child clicked');\n e.stopPropagation(); // Остановить всплытие\n});\n\nparent.addEventListener('click', () => {\n console.log('Parent clicked'); // Не выполнится\n});\n```\n\n## stopImmediatePropagation\n\nОстановить не только всплытие, но и другие слушатели на том же элементе:\n\n```javascript\nbutton.addEventListener('click', (e) => {\n console.log('Слушатель 1');\n e.stopImmediatePropagation();\n});\n\nbutton.addEventListener('click', (e) => {\n console.log('Слушатель 2'); // Не выполнится\n});\n```\n\n## preventDefault\n\nОтменить действие браузера (но событие всё ещё всплывает):\n\n```javascript\nconst form = document.querySelector('form');\n\nform.addEventListener('submit', (e) => {\n e.preventDefault(); // Не отправить форму\n console.log('Форма не отправлена');\n // Сделать кастомную обработку\n fetch('/api/submit', {\n method: 'POST',\n body: new FormData(form)\n });\n});\n```\n\n## События, которые НЕ всплывают\n\nНе все события всплывают:\n\n```javascript\nconst events = {\n 'Всплывают': ['click', 'dblclick', 'keydown', 'keyup', 'input', 'change', 'submit'],\n 'НЕ всплывают': ['focus', 'blur', 'load', 'unload', 'scroll', 'resize', 'mouseenter', 'mouseleave']\n};\n\nbutton.addEventListener('focus', (e) => {\n console.log('Focus не всплывает');\n});\n\nbutton.addEventListener('mouseenter', (e) => {\n console.log('Mouseenter не всплывает'); // Используй mouseover для всплытия\n});\n```\n\n## Проверка наличия всплытия\n\n```javascript\nbutton.addEventListener('click', (e) => {\n console.log('bubbles:', e.bubbles); // true\n console.log('cancelable:', e.cancelable); // true (можно отменить)\n});\n\nbutton.addEventListener('focus', (e) => {\n console.log('bubbles:', e.bubbles); // false\n});\n```\n\n## Создание кастомных событий с всплытием\n\n```javascript\nconst customEvent = new CustomEvent('myEvent', {\n bubbles: true, // Событие будет всплывать\n cancelable: true, // Можно отменить\n detail: { message: 'Данные события' }\n});\n\nelement.addEventListener('myEvent', (e) => {\n console.log('Моё событие:', e.detail.message);\n});\n\nelement.dispatchEvent(customEvent);\n```\n\n## Практический паттерн: Модальное окно\n\n```html\n
\n
\n

Подтверждение

\n

Вы уверены?

\n \n
\n
\n\n\n```\n\n## Производительность: Event Delegation\n\n```javascript\n// ❌ Плохо: слушатель на каждом элементе\nconst buttons = document.querySelectorAll('button');\nbuttons.forEach(button => {\n button.addEventListener('click', handleClick);\n});\n// Проблемы:\n// - 1000 кнопок = 1000 слушателей\n// - Новые кнопки не будут работать\n// - Много памяти\n\n// ✅ Хорошо: делегирование\ndocument.addEventListener('click', (e) => {\n if (e.target.matches('button')) {\n handleClick(e);\n }\n});\n// Преимущества:\n// - Всего 1 слушатель\n// - Работает с динамическими элементами\n// - Меньше памяти\n```\n\n## Отладка всплытия\n\n```javascript\nconst element = document.getElementById('test');\nconst originalStopPropagation = Event.prototype.stopPropagation;\n\nEvent.prototype.stopPropagation = function() {\n console.trace('stopPropagation вызван'); // Увидим стек вызовов\n originalStopPropagation.call(this);\n};\n```\n\nВсплытие событий - это мощный механизм, который позволяет писать эффективный и чистый код. Понимание фаз всплытия, делегирования событий и методов контроля необходимо для работы с DOM.","dateCreated":"2026-04-03T17:55:13.149008","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Как работает всплытие событий в браузере?

1.2 Junior🔥 122 комментариев
#JavaScript Core

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

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

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

Всплытие событий (Event Bubbling) в браузере

Всплытие событий - это фундаментальный механизм DOM, благодаря которому события распространяются от целевого элемента вверх по дереву к его родителям. Это один из ключевых концептов для понимания взаимодействия в JavaScript.

Как работает всплытие

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

1. Capturing phase (фаза захвата) - от window к целевому элементу
2. Target phase (целевая фаза) - на самом элементе
3. Bubbling phase (фаза всплытия) - от целевого элемента обратно к window
<div id="parent">
  <button id="child">Нажми меня</button>
</div>

<script>
const parent = document.getElementById('parent');
const child = document.getElementById('child');

// Capturing phase (true = захвата)
parent.addEventListener('click', () => {
  console.log('Parent capturing');
}, true);

// Target phase (на самом элементе)
child.addEventListener('click', () => {
  console.log('Child target');
});

// Bubbling phase (всплытие, false по умолчанию)
parent.addEventListener('click', () => {
  console.log('Parent bubbling');
}, false);

// Когда кликнем на кнопку, выведет:
// Parent capturing (фаза захвата)
// Child target (целевая фаза)
// Parent bubbling (фаза всплытия)
</script>

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

<div class="container">
  <div class="menu">
    <button class="item">Профиль</button>
    <button class="item">Настройки</button>
    <button class="item">Выход</button>
  </div>
</div>

<script>
const container = document.querySelector('.container');

// Вместо добавления слушателя на каждую кнопку,
// добавляем один слушатель на родителя
container.addEventListener('click', (e) => {
  if (e.target.classList.contains('item')) {
    console.log('Клик на кнопку:', e.target.textContent);
    // Обработать клик
  }
});

// Это называется Event Delegation (делегирование)
// Преимущества:
// - Меньше памяти (один слушатель вместо трёх)
// - Динамические элементы будут работать
// - Более чистый код
</script>

Остановка всплытия (stopPropagation)

Можно остановить всплытие события:

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

child.addEventListener('click', (e) => {
  console.log('Child clicked');
  e.stopPropagation(); // Остановить всплытие
});

parent.addEventListener('click', () => {
  console.log('Parent clicked'); // Не выполнится
});

stopImmediatePropagation

Остановить не только всплытие, но и другие слушатели на том же элементе:

button.addEventListener('click', (e) => {
  console.log('Слушатель 1');
  e.stopImmediatePropagation();
});

button.addEventListener('click', (e) => {
  console.log('Слушатель 2'); // Не выполнится
});

preventDefault

Отменить действие браузера (но событие всё ещё всплывает):

const form = document.querySelector('form');

form.addEventListener('submit', (e) => {
  e.preventDefault(); // Не отправить форму
  console.log('Форма не отправлена');
  // Сделать кастомную обработку
  fetch('/api/submit', {
    method: 'POST',
    body: new FormData(form)
  });
});

События, которые НЕ всплывают

Не все события всплывают:

const events = {
  'Всплывают': ['click', 'dblclick', 'keydown', 'keyup', 'input', 'change', 'submit'],
  'НЕ всплывают': ['focus', 'blur', 'load', 'unload', 'scroll', 'resize', 'mouseenter', 'mouseleave']
};

button.addEventListener('focus', (e) => {
  console.log('Focus не всплывает');
});

button.addEventListener('mouseenter', (e) => {
  console.log('Mouseenter не всплывает'); // Используй mouseover для всплытия
});

Проверка наличия всплытия

button.addEventListener('click', (e) => {
  console.log('bubbles:', e.bubbles); // true
  console.log('cancelable:', e.cancelable); // true (можно отменить)
});

button.addEventListener('focus', (e) => {
  console.log('bubbles:', e.bubbles); // false
});

Создание кастомных событий с всплытием

const customEvent = new CustomEvent('myEvent', {
  bubbles: true, // Событие будет всплывать
  cancelable: true, // Можно отменить
  detail: { message: 'Данные события' }
});

element.addEventListener('myEvent', (e) => {
  console.log('Моё событие:', e.detail.message);
});

element.dispatchEvent(customEvent);

Практический паттерн: Модальное окно

<div id="modal" class="modal hidden">
  <div class="modal-content">
    <h2>Подтверждение</h2>
    <p>Вы уверены?</p>
    <button class="close">Закрыть</button>
  </div>
</div>

<script>
const modal = document.getElementById('modal');

// Закрыть модаль при клике на фон
modal.addEventListener('click', (e) => {
  if (e.target === modal) { // Клик на фон, не на содержимое
    modal.classList.add('hidden');
  }
});

// Закрыть при клике на кнопку
modal.querySelector('.close').addEventListener('click', () => {
  modal.classList.add('hidden');
});

// Содержимое не закроется при клике внутри
// потому что .modal-content не === modal
</script>

Производительность: Event Delegation

// ❌ Плохо: слушатель на каждом элементе
const buttons = document.querySelectorAll('button');
buttons.forEach(button => {
  button.addEventListener('click', handleClick);
});
// Проблемы:
// - 1000 кнопок = 1000 слушателей
// - Новые кнопки не будут работать
// - Много памяти

// ✅ Хорошо: делегирование
document.addEventListener('click', (e) => {
  if (e.target.matches('button')) {
    handleClick(e);
  }
});
// Преимущества:
// - Всего 1 слушатель
// - Работает с динамическими элементами
// - Меньше памяти

Отладка всплытия

const element = document.getElementById('test');
const originalStopPropagation = Event.prototype.stopPropagation;

Event.prototype.stopPropagation = function() {
  console.trace('stopPropagation вызван'); // Увидим стек вызовов
  originalStopPropagation.call(this);
};

Всплытие событий - это мощный механизм, который позволяет писать эффективный и чистый код. Понимание фаз всплытия, делегирования событий и методов контроля необходимо для работы с DOM.

Как работает всплытие событий в браузере? | PrepBro