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

Одним из наиболее распространенных примеров события является событие клика. Когда пользователь нажимает на элемент, запускается событие щелчка. Разработчики могут прослушивать это событие с помощью прослушивателей событий и выполнять код в ответ. Точно так же наведение курсора на элемент может вызвать событие наведения, которое можно использовать для отображения дополнительной информации или изменения внешнего вида элемента.

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

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

Как правило, процесс потока событий завершается следующими тремя этапами: захват события, цель события и всплывающая пузырьковая передача событий.

Пузырьковое событие

Всплывание — это поведение по умолчанию, когда событие сначала запускается для самого внутреннего элемента, а затем перемещается наружу через родительские элементы, пока не достигнет корня дерева.

<div id="parent">
  <div id="child">
    <button id="btn">Click Me</button>
  </div>
</div>

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

  parent.addEventListener('click', () => {
    console.log('Event bubbled from parent element');
  });

  child.addEventListener('click', () => {
    console.log('Event bubbled from child element');
  });

  btn.addEventListener('click', () => {
    console.log('Event bubbled from button element');
  });
</script>

//Output
//Event bubbled from button element
//Event bubbled from child element
//Event bubbled from parent element

В этом примере всплывающая подсказка событий является поведением по умолчанию, а третий параметр не передается методу addEventListener(). При нажатии кнопки события запускаются в следующем порядке:

  1. Обработчик события элемента кнопки
  2. Обработчик событий дочернего элемента
  3. Обработчик событий родительского элемента

Захват событий

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

<div id="parent">
  <div id="child">
    <button id="btn">Click Me</button>
  </div>
</div>

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

  parent.addEventListener('click', () => {
    console.log('Event captured at parent element');
  }, true);

  child.addEventListener('click', () => {
    console.log('Event captured at child element');
  }, true);

  btn.addEventListener('click', () => {
    console.log('Event captured at button element');
  }, true);
</script>

//Output
//Event captured at parent element
//Event captured at child element
//Event captured at button element

В этом примере захват событий включается путем передачи true в качестве третьего параметра методу addEventListener(). При нажатии кнопки события запускаются в следующем порядке:

  1. Обработчик событий родительского элемента
  2. Обработчик событий дочернего элемента
  3. Обработчик события элемента кнопки

Событие.stopPropagation()

Разработчики могут контролировать распространение событий с помощью метода stopPropagation(). Этот метод останавливает дальнейшее распространение события через DOM на этапах захвата и всплытия, позволяя разработчикам ограничить область действия события определенным элементом. Однако это не предотвращает появление поведения по умолчанию.

<div id="parent">
  <div id="child">
    <button id="btn">Click Me</button>
  </div>
</div>

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

  parent.addEventListener('click', (event) => {
    console.log('Event captured at parent element');
  }, true);

  child.addEventListener('click', (event) => {
    console.log('Event captured at child element');
    event.stopPropagation(); // stop event propagation
  }, true);

  btn.addEventListener('click', (event) => {
    console.log('Event captured at button element');
  }, true);
</script>

//Output
//Event captured at parent element
//Event captured at child element

В этом примере включен режим захвата, и метод stopPropagation() вызывается в прослушивателе событий элемента child, чтобы предотвратить дальнейшее распространение события к элементу button. При нажатии кнопки события запускаются в следующем порядке:

  1. Обработчик событий родительского элемента
  2. Обработчик событий дочернего элемента

Распространение события на элемент кнопки остановлено, поэтому обработчик события элемента кнопки не запускается.

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