Что такое события в JavaScript и как с ними работать?

Первоначально опубликовано в моем личном блоге.

События в JavaScript позволяют разработчикам отслеживать изменения в документе и обрабатывать их по мере необходимости. Например, вы можете прослушать, когда нажимается кнопка, чтобы открыть модальное окно. Другой пример — показ кнопки «прокрутить вверх», когда пользователь прокручивает страницу на половину.

Эта статья поможет новичкам понять, что такое события в JavaScript и как их обрабатывать.

Зачем использовать события

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

События также полезны для обнаружения различных состояний вашего сайта. Например, обнаружение изменения размера экрана может помочь обеспечить отзывчивость определенных элементов на странице.

Список случаев, когда события могут быть полезны, бесконечен. События являются неотъемлемой частью веб-разработки на JavaScript, и важно понимать, как их использовать.

Добавление обработчика событий

Чтобы слушать события, вы можете использовать метод addEventListener. Этот метод доступен для каждого элемента и узла в документе.

addEventListener принимает три параметра: первый параметр — имя события, которое нужно прослушать; второй параметр — функция, которая обрабатывает это событие; третий параметр — необязательный параметр, который позволяет задать дополнительные параметры для обработчика.

В большинстве случаев вам нужно использовать только первые два параметра. Вот пример обработки события click для кнопки:

const button = document.querySelector("button");
button.addEventListener("click", function (e) {
    alert("Button clicked");
});
Войти в полноэкранный режим Выйти из полноэкранного режима

Этот пример извлекает первую кнопку на странице и, когда кнопка нажата, показывает предупреждение.

Может ли событие иметь более одного обработчика?

Одно и то же событие может иметь множество обработчиков. При возникновении события обработчики срабатывают один за другим.

Объект события

Как видите, функция, переданная в качестве второго параметра в addEventListener, получила аргумент e. Это объект Event. Этот объект может иметь различные свойства в зависимости от его базового типа. Однако у него есть несколько общих важных свойств.

Часто используемым свойством объекта Event является свойство target. Это элемент, на котором сработало событие. Это может быть полезно, когда у вас есть один и тот же обработчик для нескольких элементов.

Например:

document.querySelector("input").addEventListener("change", function (e) {
    alert(e.target.value);
});
Вход в полноэкранный режим Выйти из полноэкранного режима

Этот фрагмент кода добавляет обработчик события для первого элемента input на событие change. Событие change срабатывает, когда вы изменяете значение ввода, а затем перемещаете фокус с ввода (например, нажимаете на что-то другое на странице).

Когда происходит событие change и срабатывает обработчик, значение ввода извлекается с помощью e.target.value и используется в оповещении.

Предотвращение поведения события по умолчанию

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

Чтобы предотвратить поведение события по умолчанию, вы можете использовать метод preventDefault() для объекта Event.

Например:

const a = document.querySelector("a.some-link");
a.addEventListener("click", function (e) {
    e.preventDefault();
    if(confirm("Are you sure?")) {
      window.location.href = e.target.href;
    }
});
Вход в полноэкранный режим Выход из полноэкранного режима

Это добавляет обработчик событий click на ссылку, имеющую класс some-link. В обработчике события e.preventDefault() используется для предотвращения поведения по умолчанию — открытия страницы, указанной в атрибуте href.

Затем он показывает пользователю окно подтверждения, и если пользователь нажимает Да в окне подтверждения, он открывает страницу, как и ожидалось.

Запретить другим обработчикам обрабатывать это событие

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

Есть два метода, которые можно использовать, чтобы запретить другим обработчикам обрабатывать одно и то же событие: stopPropagation и stopImmediatePropagation.

stopPropagation используется для предотвращения обработки события другими обработчиками событий во время фазы пузырения.

Пузырение — это когда у вас есть одно и то же событие на дочернем и родительском элементах. Сначала событие срабатывает на дочернем элементе, а затем «перетекает» на родительский элемент.

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

Чтобы предотвратить обработку события последующими обработчиками, вы можете использовать stopImmediatePropagation.

Например:

const button = document.querySelector("button");

button.addEventListener("click", function (e) {
  e.stopImmediatePropagation();
  alert("Hello!");
});

button.addEventListener("click", function (e) {
  alert("Bye!")
})
Вход в полноэкранный режим Выход из полноэкранного режима

Хотя у кнопки есть два обработчика событий, которые слушают событие click, будет запущен только первый, поскольку он вызывает функцию stopImmediatePropagation.

Разница между preventDefault, stopPropagation и stopImmediatePropagation

preventDefault предотвращает только поведение события по умолчанию. Однако это не мешает другим обработчикам обрабатывать событие.

stopPropagation и stopImmediatePropagation только предотвращают обработку события другими обработчиками. Однако они не предотвращают поведение события по умолчанию.

Если вы хотите предотвратить как поведение по умолчанию, так и обработку события другими обработчиками, используйте preventDefault с stopPropagation или stopImmediatePropagation.

Обработка событий на динамических элементах

Рассмотрим следующий пример:

const buttons = document.querySelectorAll(".btn");

buttons.forEach((btn) => {
  btn.addEventListener("click", function (e) {
    alert("Hello!");
  });
})

//create new button
const button = document.createElement('button');
button.classList.add('btn');
button.textContent = "Bye";
document.body.append(button);
Вход в полноэкранный режим Выход из полноэкранного режима

В этом примере вы сначала получаете все кнопки, имеющие класс btn. Затем вы перебираете эти кнопки и добавляете слушатель событий, который просто показывает оповещение «Hello» при нажатии на кнопку.

Затем вы динамически создаете новую кнопку, добавляете класс btn к этой кнопке и добавляете ее в body документа.

Если вы попробуете нажать на кнопки, которые были добавлены в HTML документа или которые были добавлены до добавления слушателя событий, предупреждение будет показано, как и ожидалось. Однако если вы нажмете на новую кнопку, предупреждение показано не будет.

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

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

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

Например, вы можете преобразовать предыдущий пример в следующий:

document.body.addEventListener("click", function (e) {
  if (e.target.classList.contains("btn")) {
    alert("Hello!");
  }
})

//create new button
const button = document.createElement('button');
button.classList.add('btn');
button.textContent = "Bye";
document.body.append(button);
Войти в полноэкранный режим Выход из полноэкранного режима

Вы добавляете обработчик события click на body. В обработчике вы проверяете, имеет ли e.target класс btn, и выполняете необходимое действие, только если имеет.

Теперь, когда любой из элементов, имеющих класс btn, динамически или изначально созданный, будет щелкнут, обработчик события будет запущен для них.

Однако при таком подходе обработчик событий будет запускаться при каждом событии щелчка на теле. Поэтому важно тщательно обрабатывать его в зависимости от цели.

Удаление обработчика событий

В некоторых случаях вы можете захотеть удалить обработчик события для элемента. Для этого можно использовать метод removeEventListener. Этот метод доступен для каждого элемента и узла в документе.

Этот метод получает те же параметры, что и addEventListener. Важно передать ту же функцию, которую вы передали в addEventListener. По этой причине люди обычно определяют функцию отдельно, а затем передают ее в addEventListener и removeEventListener.

Например:

const button = document.querySelector("button");

function handleClick (e) {
  alert("Hello");
}

button.addEventListener("click", handleClick);

//some time later
button.removeEventListener("click", handleClick);
Войти в полноэкранный режим Выйти из полноэкранного режима

Заключение

Эта статья лишь поверхностно коснулась темы событий и помогла вам лучше понять их. Чтобы узнать больше о событиях в JavaScript, ознакомьтесь со следующими ресурсами:

  1. Введение в события
  2. Справочник по событиям

Оцените статью
devanswers.ru
Добавить комментарий