StopPropagation: примеры (JAVASCRIPT)

Использование stopPropagation для контроля событий
Раздел: DOM, События
stopPropagation: undefined

Основные сведения о stopPropagation

Метод stopPropagation() принадлежит объекту события в JavaScript. Он останавливает дальнейшее всплытие (bubbling) текущего события по DOM-дереву. При вызове этого метода событие не будет передано родительским элементам, но обработчики на текущем элементе выполнятся полностью.

Использование метода актуально при необходимости изолировать обработку события на определенном уровне DOM, предотвращая запуск обработчиков, назначенных на предков элемента.

Метод не принимает аргументов и не возвращает значений (возвращает undefined).

Синтаксис:

event.stopPropagation();

Простые примеры использования

Пример 1: Остановка всплытия клика.

<div id='parent'> Родитель
  <button id='child'>Кнопка</button>
</div>

<script>
  document.getElementById('parent').addEventListener('click', function() {
    console.log('Клик по родителю');
  });

  document.getElementById('child').addEventListener('click', function(event) {
    event.stopPropagation();
    console.log('Клик по кнопке');
  });
</script>

Результат:

При клике на кнопку в консоли будет только 'Клик по кнопке'. Сообщение от родителя не появится.

Пример 2: Использование с третьим параметром addEventListener.

// Обработчик в фазе захвата (capturing)
document.documentElement.addEventListener('click', function() {
  console.log('HTML');
}, true);

// Обработчик на элементе
document.querySelector('div').addEventListener('click', function(event) {
  event.stopPropagation();
  console.log('Div');
});

Результат:

При клике на div будет выведено 'HTML' (так как фаза захвата происходит до фазы всплытия), а затем 'Div'. Всплытие наверх от div будет остановлено.

Альтернативные методы в JavaScript

stopImmediatePropagation() — останавливает всплытие события и предотвращает выполнение любых других обработчиков на текущем элементе. Метод stopPropagation() этого не делает.

preventDefault() — отменяет стандартное действие браузера, связанное с событием (например, отправку формы или переход по ссылке). Не влияет на всплытие.

return false — в обработчиках, назначенных через атрибут (onclick='...') или через свойство (element.onclick = ...), команда return false выполняет и stopPropagation, и preventDefault. В обработчиках, добавленных через addEventListener, return false не останавливает всплытие.

Распространенные ошибки

1. Путаница с preventDefault. Метод stopPropagation не отменяет действие по умолчанию.

// НЕПРАВИЛЬНО: ожидание отмены перехода по ссылке
document.querySelector('a').addEventListener('click', function(event) {
  event.stopPropagation(); // Переход по ссылке все равно произойдет
});

2. Использование в асинхронных обработчиках. Если обработчик события асинхронный, вызов stopPropagation может быть бесполезен, так как событие уже всплыло.

// Не сработает как ожидается
element.addEventListener('click', async function(event) {
  await someAsyncTask();
  event.stopPropagation(); // Событие уже всплыло
});

История изменений

Метод stopPropagation не претерпел значительных изменений в последних версиях ECMAScript. Он является частью стандарта DOM Events Level 2 и выше. В современных браузерах метод работает стабильно. Единственное заметное уточнение — в спецификации четко обозначено, что метод не влияет на события в фазе захвата (capturing phase), которые уже были вызваны.

Расширенные примеры

Пример 1: Остановка всплытия для делегирования событий с фильтрацией.

Пример javascript
<ul id='list'>
  <li>Элемент 1 <button class='btn'>Удалить</button></li>
  <li>Элемент 2 <button class='btn'>Удалить</button></li>
</ul>

<script>
  document.getElementById('list').addEventListener('click', function(event) {
    if (event.target.classList.contains('btn')) {
      event.stopPropagation(); // Останавливаем всплытие, чтобы клик по кнопке не считался кликом по li
      event.target.closest('li').remove();
    } else {
      console.log('Клик по элементу списка');
    }
  });
</script>

Результат:

При клике на кнопку 'Удалить' соответствующий элемент списка удаляется, а сообщение в консоль не выводится.

Пример 2: Комбинирование stopPropagation и stopImmediatePropagation.

Пример javascript
const div = document.querySelector('div');

div.addEventListener('click', function(event) {
  console.log('Первый обработчик');
  event.stopImmediatePropagation();
});

div.addEventListener('click', function(event) {
  console.log('Второй обработчик'); // Этот обработчик не выполнится
});

document.body.addEventListener('click', function() {
  console.log('Тело документа'); // Этот обработчик также не выполнится
});

Результат:

При клике на div в консоли будет только 'Первый обработчик'.

Пример 3: Взаимодействие с пользовательскими событиями.

Пример javascript
const elem = document.getElementById('myElem');

elem.addEventListener('myEvent', function(event) {
  console.log('Событие myEvent получено');
  event.stopPropagation();
});

document.body.addEventListener('myEvent', function() {
  console.log('myEvent на body'); // Не сработает из-за stopPropagation
});

const ev = new Event('myEvent', { bubbles: true });
elem.dispatchEvent(ev);

Результат:

В консоли будет только 'Событие myEvent получено'.

Похожие механизмы в других языках

Python (tkinter): В библиотеке tkinter для GUI можно вернуть 'break' из обработчика события, чтобы остановить его дальнейшее распространение.

import tkinter as tk

def handler(event):
    print('Обработчик')
    return 'break'  # Остановка распространения

root = tk.Tk()
frame = tk.Frame(root)
frame.bind('<Button-1>', handler)
frame.pack()
root.mainloop()

C# (Windows Forms): В обработчике события можно установить свойство Handled объекта EventArgs в true, чтобы предотвратить дальнейшую обработку события некоторыми элементами управления.

private void button1_Click(object sender, EventArgs e)
{
    e.Handled = true; // Аналог остановки распространения
}

В PHP, MySQL или чистом C нет прямых аналогов, так как эти языки не работают с DOM-событиями в браузере.

JS stopPropagation function comments

En
StopPropagation Prevents further propagation of the current event in the capturing and bubbling phases