W3docs

Обработка событий в DOM

Обработка событий JavaScript в DOM: addEventListener, removeEventListener, объект event, preventDefault, всплытие событий и делегирование с примерами.

Введение в события JavaScript

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

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

Три способа обработки событий

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

ПодходПримерНесколько обработчиков?Рекомендуется
Встроенный HTML-атрибут<button onclick="doX()">НетНет — смешивает разметку и логику
Свойство DOMelement.onclick = fnНет (побеждает последний)Только для простых случаев
addEventListener()element.addEventListener("click", fn)ДаДа — современный стандарт
<button id="propBtn">Click me</button>

<script>
  const btn = document.getElementById("propBtn");

  // 1. DOM property — assigning again overwrites the previous handler
  btn.onclick = function () {
    alert("Handled by the onclick property");
  };

  // 2. addEventListener — adds without overwriting; you can attach many
  btn.addEventListener("click", function () {
    console.log("Also handled by addEventListener");
  });
</script>

Оба обработчика выше сработают по клику. Если присвоить btn.onclick второй раз, первое присваивание будет молча потеряно — именно поэтому предпочтительнее использовать addEventListener(). В остальной части главы используется addEventListener().

Распространённые события JavaScript

Событие click

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

<button id="clickButton">Click Me</button>

<script>
  document.getElementById("clickButton").addEventListener("click", function () {
    alert("Button was clicked!");
  });
</script>

В этом примере к кнопке с идентификатором clickButton добавлен слушатель события. При нажатии на кнопку появится диалоговое окно с сообщением «Button was clicked!».

Событие mouseover

Событие mouseover срабатывает, когда указатель мыши перемещается на элемент. (Обратное событие, mouseout, срабатывает, когда указатель покидает элемент.)

<p id="mouseoverText">Hover over me!</p>

<script>
  document.getElementById("mouseoverText").addEventListener("mouseover", function () {
    this.style.color = "red";
  });
</script>

В этом примере к абзацу с идентификатором mouseoverText добавлен слушатель события. При наведении мыши на абзац цвет его текста меняется на красный.

Событие keydown

Событие keydown срабатывает, когда пользователь нажимает клавишу, пока элемент находится в фокусе. Обработчик получает объект event, свойство event.key которого содержит значение нажатой клавиши.

<input type="text" id="inputField" placeholder="Type something..." />

<script>
  document.getElementById("inputField").addEventListener("keydown", function (event) {
    alert(`Key pressed: ${event.key}`);
    this.value = '';
  });
</script>

В этом примере к полю ввода с идентификатором inputField добавлен слушатель события. При нажатии клавиши, пока поле ввода находится в фокусе, нажатая клавиша отображается в диалоговом окне.

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

Каждый обработчик вызывается с одним аргументом: объектом события. Он описывает произошедшее и предоставляет методы для управления событием. Наиболее полезные члены:

  • event.target — элемент, на котором событие фактически возникло (например, конкретная нажатая кнопка).
  • event.currentTarget — элемент, к которому прикреплён слушатель. Внутри обычной функции это то же самое, что this.
  • event.type — имя события, например "click".
  • event.preventDefault() — отменяет действие браузера по умолчанию (переход по ссылке, отправка формы).
  • event.stopPropagation() — останавливает дальнейшее всплытие события по DOM.
<a id="link" href="https://www.w3docs.com">Visit W3docs</a>

<script>
  document.getElementById("link").addEventListener("click", function (event) {
    event.preventDefault(); // stop the browser from navigating away
    console.log("type:", event.type);          // "click"
    console.log("target id:", event.target.id); // "link"
  });
</script>

Здесь preventDefault() предотвращает навигацию, позволяя выполнить собственную логику — распространённый шаблон для одностраничных приложений и пользовательской валидации форм.

Информация

Внутри стрелочной функции this не привязывается к элементу. Используйте event.currentTarget (или обычную function), когда вам нужна ссылка на элемент, к которому прикреплён слушатель. Подробнее см. в разделе стрелочные функции.

Добавление слушателей событий

Метод addEventListener()

Метод addEventListener() прикрепляет обработчик события к элементу, не перезаписывая существующие обработчики. Это означает, что можно добавить несколько слушателей — даже для одного типа события — к одному элементу. Его сигнатура: element.addEventListener(type, handler, options), где options позволяет настроить поведение (once, capture, passive).

<button id="multiEventButton">Click or Hover</button>

<script>
  const button = document.getElementById("multiEventButton");

  button.addEventListener("click", function () {
    alert("Button clicked!");
  });

  button.addEventListener("mouseover", function () {
    button.style.backgroundColor = "lightblue";
  });
</script>

В этом примере к кнопке с идентификатором multiEventButton добавлены два слушателя событий. Один слушатель вызывает диалоговое окно при нажатии на кнопку, а другой меняет цвет фона кнопки при наведении мыши.

Информация

Используйте addEventListener() для добавления нескольких слушателей событий к одному элементу без перезаписи существующих обработчиков.

Удаление слушателей событий

Метод removeEventListener()

Метод removeEventListener() отсоединяет обработчик, добавленный с помощью addEventListener(). Важно: необходимо передать точно ту же ссылку на функцию, которая была добавлена, поэтому для последующего удаления слушателя необходимы именованные функции.

<button id="removeEventButton">Click Me</button>

<script>
  function showAlert() {
    alert("This will be removed after first click");
  }

  const button = document.getElementById("removeEventButton");
  button.addEventListener("click", showAlert);

  button.addEventListener("click", function () {
    button.removeEventListener("click", showAlert);
  });
</script>

В этом примере к кнопке с идентификатором removeEventButton добавлен слушатель события, вызывающий диалоговое окно. Второй слушатель удаляет этот обработчик после первого клика. Обратите внимание: removeEventListener требует ссылку на тот же самый объект функции, который использовался в addEventListener. Именно поэтому анонимные функции не могут быть удалены позднее — каждое объявление создаёт новый, отдельный объект функции.

Информация

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

Распространение событий и делегирование

Когда событие возникает на элементе, оно не останавливается там. По умолчанию оно проходит две фазы: сначала захват (от верхушки DOM до целевого элемента), затем всплытие (от целевого элемента обратно к корню). Большинство обработчиков срабатывают во время фазы всплытия, поэтому клик по кнопке также достигает слушателя клика на родительском <div>.

Это всплытие обеспечивает делегирование событий: вместо того чтобы добавлять слушатель к каждому дочернему элементу, достаточно добавить один слушатель к общему родителю и читать event.target, чтобы определить, по какому дочернему элементу был выполнен клик.

<ul id="menu">
  <li>Home</li>
  <li>About</li>
  <li>Contact</li>
</ul>

<script>
  // One listener handles clicks on any current OR future <li>
  document.getElementById("menu").addEventListener("click", function (event) {
    if (event.target.tagName === "LI") {
      console.log("You clicked:", event.target.textContent);
    }
  });
</script>

Один слушатель на <ul> обрабатывает каждый <li>, включая элементы, добавленные в список позже, — это намного эффективнее, чем подключать обработчик к каждому элементу по отдельности. Для более глубокого изучения фаз и метода stopPropagation() смотрите раздел всплытие и захват.

Лучшие практики

Используйте делегирование событий

Добавьте один слушатель события к родительскому элементу для управления событиями всех дочерних элементов. Это улучшает производительность и сокращает количество слушателей событий.

Избегайте анонимных функций в качестве обработчиков событий

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

Удаляйте слушателей событий, когда они больше не нужны

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

Минимизируйте количество слушателей событий

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

Используйте опцию once в addEventListener

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

button.addEventListener("click", function handler() {
  console.log("Triggered once");
}, { once: true });

Правильно используйте preventDefault и stopPropagation

Применяйте event.preventDefault() и event.stopPropagation() обдуманно, чтобы управлять поведением событий, не мешая другим обработчикам.

Применяйте debounce или throttle для обработчиков событий

Используйте методы debouncing или throttling для оптимизации производительности обработчиков событий, которые срабатывают часто, например при прокрутке или изменении размера окна.

Заключение

Владение событиями JavaScript крайне важно для создания динамичных и интерактивных веб-приложений. Понимание того, как использовать события click, mouseover и keydown, а также как добавлять и удалять слушателей событий с помощью addEventListener() и removeEventListener(), позволит вам значительно улучшить взаимодействие пользователей с вашими веб-страницами.

Практика

Практика
Какие из следующих утверждений об обработке событий в DOM верны?
Какие из следующих утверждений об обработке событий в DOM верны?
Was this page helpful?