Прослушивание событий в JavaScript

Многие веб-приложения опираются на события для выполнения своих функций. Человек взаимодействует с интерфейсом — это порождает событие, обычно связанное с периферийным устройством, например мышью или клавиатурой.
Когда устройство создаёт событие, программа может «подслушать» его и выполнить соответствующее поведение. В этом руководстве вы научитесь слушать события с помощью JavaScript и строить устойчивую логику взаимодействия.
Что такое программирование, управляемое событиями
Event-driven programming — это парадигма, в которой выполнение логики привязано к событиям. Такую модель можно реализовать в любом языке высокого уровня, но она особенно распространена в средах с пользовательским интерфейсом, например в JavaScript в браузере.
Определение: событие — это объект, который описывает произошедшее действие (клик, ввод, изменение размера окна и т.д.).
Что такое слушатель событий
Слушатель событий — это функция, которая запускает заранее определённый процесс, когда зарегистрированное событие происходит. Проще: слушатель “слушает” действие, а затем вызывает функцию-обработчик.
События бывают разные: события мыши, клавиатуры, окна, формы, кастомные события и т.д.
Создание слушателя событий в JavaScript
Любой элемент в DOM может иметь слушатель. Для этого есть метод addEventListener(), который является методом интерфейса EventTarget. Объекты, которые поддерживают события, реализуют этот интерфейс — window, document и отдельные элементы страницы.
Простейшая структура вызова:
element.addEventListener("event", functionToExecute);Где:
- element — любой HTML-элемент (кнопка, параграф и т.д.)
- “event” — строка с именем события
- functionToExecute — ссылка на функцию-обработчик
Ниже создадим простую страницу с элементами для демонстрации слушателей:
Документ
Добро пожаловать
Привет, добро пожаловать на мой сайт.
Информация о пользователе
Код выше создаёт простую страницу, которая подключает файл app.js. В этом файле будем добавлять слушатели.
Файл app.js — простой обработчик клика
document.querySelector('.btn').addEventListener("click", clickDemo);
function clickDemo(){
console.log("Привет")
}Этот код находит первую кнопку на странице через querySelector() и добавляет ей слушатель события “click”. При нажатии в консоли браузера появится строка “Привет”.
Связанный пример: как использовать селекторы DOM
Вывод при событии “click”
События мыши
Интерфейс MouseEvent представляет события, возникающие при взаимодействии пользователя с мышью. Частые примеры:
- click
- dblclick
- mousemove
- mouseover
- mouseout
- mouseup
- mousedown
Событие click происходит, когда пользователь нажимает и отпускает кнопку мыши над элементом. dblclick — двойной клик, который по сути совмещает два click-события.
Важно: addEventListener позволяет навесить несколько слушателей на один элемент для разных событий.
Добавление dblclick для первой кнопки
document.querySelector('.btn').addEventListener("dblclick", dblclickDemo);
function dblclickDemo(){
alert("Это демонстрация события двойного клика")
}После добавления этого кода двойной клик по первой кнопке вызовет alert. Заметьте: двойной клик генерирует два click-события и одно dblclick, поэтому все слушатели при этом могут сработать.
Клавиатурные события
Интерфейс KeyboardEvent слушает взаимодействие с клавиатурой. На практике сейчас используются два события: keydown и keyup. Событие keypress помечено как deprecated и не рекомендуется.
- keydown — происходит при нажатии клавиши
- keyup — при отпускании клавиши
Лучший элемент для демонстрации — input поля.
Добавление слушателя клавиатуры в app.js
let greetings = document.querySelector('p');
document.querySelector('input').addEventListener("keyup", captureInput);
function captureInput(e){
greetings.innerText = (`Привет ${e.target.value}, добро пожаловать на мой сайт.`)
}Здесь мы получаем параграф и input, добавляем слушатель keyup, и при каждом отпускании клавиши обновляем текст в параграфе. Параметр e — объект события; его свойство target ссылается на элемент, с которым взаимодействовал пользователь.
В примере выше при вводе имени параграф будет показывать введённое значение.
Параметры addEventListener и управление распространением событий
Метод addEventListener принимает третий необязательный параметр — options или useCapture (устаревшая форма). Параметры позволяют гибко управлять поведением слушателя:
- capture (boolean) — если true, слушатель срабатывает на фазе захвата (capture), до фазы всплытия
- once (boolean) — если true, слушатель удаляется автоматически после первого срабатывания
- passive (boolean) — если true, сообщает браузеру, что обработчик не вызывает preventDefault(); полезно для прокрутки и повышения производительности
Пример с опциями:
button.addEventListener('click', handler, { capture: false, once: true, passive: false });Важно: использование passive: true для событий прокрутки и touch-эвентов улучшит отзывчивость, потому что браузер не будет ждать возможного preventDefault().
Фазы события: захват и всплытие
Механика распространения события в DOM состоит из трёх фаз:
- Фаза захвата (capture) — событие идёт сверху вниз от document к целевому элементу.
- Целевая фаза — обработчики на целевом элементе.
- Фаза всплытия (bubble) — событие идёт от целевого элемента вверх к document.
По умолчанию addEventListener добавляет слушатель на фазе всплытия (bubble). Установив capture: true, вы подпишетесь на фазу захвата.
Если нужно остановить дальнейшее распространение события, используйте e.stopPropagation(). Чтобы отменить стандартное действие (например отправку формы по Enter), используйте e.preventDefault().
Делегирование событий (event delegation)
Делегирование — шаблон, при котором слушатель вешается на родительский контейнер вместо каждого дочернего элемента. Это экономит ресурсы и упрощает динамически добавляемые элементы.
Пример: у нас список кнопок внутри контейнера #about. Вместо навешивания слушателя на каждую кнопку — повесим один слушатель на контейнер:
document.getElementById('about').addEventListener('click', function(e){
const btn = e.target.closest('.btn');
if (!btn) return; // клик не по кнопке
// обработка кнопки
console.log('Нажата кнопка с id:', btn.id);
});Плюсы:
- меньше слушателей в DOM
- подходит для динамических элементов
Ограничения и когда это не подходит:
- сложнее срабатывание для событий, которые не всплывают
- требуются дополнительные проверки целевого элемента (e.target)
Когда слушатели могут «подводить» — распространённые ошибки
- Навесили слишком много слушателей на элементы с большой частотой событий (mousemove) — может быть медленно.
- Использовали устаревшие события (keypress) — потеря кроссбраузерности.
- Не учли порядок фаз и случайно остановили propagation там, где это мешает другим компонентам.
- Делегирование не работает для событий, которые не всплывают (например focus) — используйте focusin/focusout или добавляйте слушатели напрямую.
Практические рекомендации по производительности и доступности
- Используйте делегирование для большого числа однотипных элементов.
- Для интенсивных событий (scroll, resize, mousemove) применяйте throttle/debounce или passive listeners.
- Не полагайтесь только на события мыши — обеспечьте клавиатурный доступ и aria-атрибуты для доступности.
- Проверяйте, не добавляете ли вы несколько идентичных слушателей (memory leak).
Важно: passive: true — хороший выбор для scroll и touch-обработчиков. Но если вам нужно preventDefault(), passive нельзя использовать.
Чек-листы по ролям
Frontend-разработчик:
- Использовать делегирование, где это оправдано
- Выбирать { once: true } для одноразовых действий
- Применять passive для прокрутки
- Тестировать в мобильных браузерах на touch-события
Тестировщик / QA:
- Проверить клавиатурную навигацию (Tab, Enter, Space)
- Проверить порядок срабатывания обработчиков
- Проверить отмену действий (preventDefault) и stopPropagation
Продакт-менеджер:
- Уточнить ожидаемое UX при двойных кликах и сочетаниях клавиш
- Описать критерии приёмки для событий (см. ниже)
Критерии приёмки
- Клик по кнопке вызывает требуемое действие и не приводит к лишним побочным эффектам.
- Двойной клик выполняет свою задачу и не дублирует результаты от одиночного клика.
- Ввод в поле обновляет UI в реальном времени без задержек.
- Для динамически добавленных элементов обработчики работают корректно.
Набор тестов и сценариев (минимум)
- Нажать, двойной клик, зажать и отпустить — проверить разные mouse-события.
- Ввод текста в input — проверить keydown/keyup и корректность e.target.value.
- Поставить passive слушатель на scroll — убедиться, что страница не тормозит.
- Стоп распространения: добавить слушатель выше в DOM и проверить, останавливается ли propagation.
Шпаргалка: распространённые события (cheat sheet)
- Клики: click, dblclick
- Движение мыши: mousemove, mouseover, mouseout
- Кнопки мыши: mousedown, mouseup
- Клавиатура: keydown, keyup
- Формы: submit, input, change
- Окно: load, resize, scroll
Скорректированные примеры для реальных задач
- Обработчик один раз:
const btn = document.querySelector('.btn');
btn.addEventListener('click', handleOnce, { once: true });
function handleOnce(e){
// выполнение только при первом клике
}- Делегирование с проверкой роли кнопки:
document.body.addEventListener('click', (e) => {
const btn = e.target.closest('[data-action]');
if (!btn) return;
const action = btn.dataset.action;
// switch по action
});Небольшая методология добавления событий в проект
- Определите гранулярность: прямой слушатель или делегирование.
- Выберите опции (capture/once/passive) исходя из сценария.
- Протестируйте на клавиатуре и мобильных устройствах.
- Покройте unit/e2e тестом критичные сценарии (ввод, клики, отправка).
- Мониторьте производительность и memory leaks.
Небольшой словарь (1‑строчно)
- EventTarget — объект, поддерживающий события (window, document, элемент).
- addEventListener — метод для подписки на событие.
- propagation — распространение события по дереву DOM.
- capture — фаза захвата события сверху вниз.
- bubble — фаза всплытия события снизу вверх.
Заключение
Вы узнали основы прослушивания событий в браузере: как работает addEventListener, какие бывают mouse и keyboard события, как управлять фазами распространения и какие options доступны. Также рассмотрели делегирование, шаблоны проектирования для событий и практические рекомендации по производительности и доступности.
Краткие рекомендации:
- Используйте делегирование для множества элементов
- Применяйте passive для scroll/touch
- Обязательно тестируйте клавиатурную доступность
Если нужно, в дополнение могу подготовить готовые шаблоны для популярных библиотек (React/Vue) или набор e2e-тестов для событий.
Похожие материалы
Raspberry Pi 3: установка и обновление
Презентации в Figma — пошаговое руководство
Синхронизация света с музыкой для Хэллоуина
LED‑глаза на батарейках — простой DIY
Как сделать изображение резким — Photoshop, GIMP, онлайн