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

Digital-студия WNDER

Что такое события и зачем они нужны

Событие — это сигнал от браузера: «Эй, пользователь что-то сделал!» Например, кликнул мышкой, нажал клавишу, прокрутил колесо. Ваша задача — поймать этот сигнал и отреагировать. В JavaScript для этого есть специальные методы: addEventListener и старый добрый onclick. Но не спешите хвататься за первый попавшийся.

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

Основные события мыши: клики, наведение, колесо

Мышь — главный инструмент пользователя. Вот список событий, которые вы будете использовать чаще всего:

  • click — самый частый гость. Срабатывает после полного нажатия и отпускания кнопки.
  • mousedown и mouseup — нажатие и отпускание кнопки. Полезно для drag-and-drop.
  • mousemove — движение курсора. Осторожно: может срабатывать сотни раз в секунду.
  • mouseover и mouseout — наведение и уход курсора с элемента.
  • wheel — прокрутка колеса. Даёт информацию о направлении и скорости.

Пример простого обработчика клика:

const button = document.querySelector('.my-button');
button.addEventListener('click', (event) => {
  console.log('Кнопка нажата!', event.target);
  // event.target — элемент, по которому кликнули
});

Обратите внимание на объект event. В нём куча полезной информации: координаты курсора (clientX, clientY), какая кнопка мыши нажата (button), был ли зажат Ctrl или Shift (ctrlKey, shiftKey).

Частая ошибка новичков — вешать обработчик на каждый элемент списка. Если у вас 1000 кнопок, вы создадите 1000 слушателей. Это медленно и неэффективно. Вместо этого используйте делегирование событий: вешайте один обработчик на родительский контейнер и проверяйте event.target.

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

Клавиатура: от простых нажатий до горячих клавиш

С клавиатурой всё немного сложнее. Есть три основных события:

  • keydown — клавиша нажата (срабатывает до того, как символ появится в поле ввода).
  • keyup — клавиша отпущена.
  • keypress — устаревшее, но ещё встречается. Лучше не использовать.

Чтобы узнать, какая клавиша нажата, используйте свойство event.key (например, 'Enter', 'a', 'ArrowUp') или event.code (физический код клавиши, например, 'KeyA'). Для горячих клавиш комбинируйте с ctrlKey, altKey, shiftKey, metaKey.

Пример: обрабатываем нажатие Ctrl+Enter для отправки формы.

document.addEventListener('keydown', (event) => {
  if (event.ctrlKey && event.key === 'Enter') {
    event.preventDefault(); // отменяем стандартное поведение
    console.log('Отправка формы по Ctrl+Enter');
    // здесь вызов функции отправки
  }
});

Почему важно вызывать preventDefault? Потому что некоторые клавиши имеют встроенное поведение в браузере (пробел прокручивает страницу, Enter отправляет форму). Если вы хотите свой сценарий, отменяйте стандарт.

Ещё один нюанс: событие keydown срабатывает при удержании клавиши многократно (автоповтор). Если вам нужно однократное действие, используйте флаг или проверяйте event.repeat.

Параметры и свойства событий: таблица для быстрого доступа

Когда вы ловите событие, у вас в руках объект с кучей свойств. Вот основные, которые пригодятся в 90% случаев:

Свойство Для чего Пример
target Элемент, на котором произошло событие event.target — кнопка или поле ввода
currentTarget Элемент, к которому привязан обработчик Всегда тот, на ком вызван addEventListener
clientX / clientY Координаты курсора относительно окна Позиция мыши при клике
key / code Символ или физический код клавиши 'Enter' или 'KeyA'
ctrlKey, shiftKey, altKey, metaKey Были ли зажаты модификаторы true или false
preventDefault() Отменяет стандартное действие браузера Для пробела или Enter
stopPropagation() Останавливает всплытие события Чтобы клик не дошёл до родителя
Лайфхак: если вы обрабатываете клик внутри модального окна, не забудьте про stopPropagation, иначе клик «провалится» на подложку и закроет окно. Или проверяйте event.target.

Практические советы и типичные ошибки

Опыт приходит с ошибками. Вот несколько грабель, на которые лучше не наступать.

  • Не забывайте удалять обработчики. Если вы добавили слушатель на window, а потом компонент удалили, обработчик останется висеть и может вызвать утечку памяти. Используйте removeEventListener или AbortController.
  • Не злоупотребляйте mousemove. Это событие срабатывает очень часто. Если внутри тяжёлые вычисления, используйте throttle или debounce.
  • Проверяйте event.key, а не keyCode. keyCode устарел и может различаться в браузерах. event.key даёт читаемый символ.
  • Не блокируйте контекстное меню без причины. Пользователи злятся, когда не могут скопировать текст. Если отключаете right click, объясните зачем.

Пример использования AbortController для автоматического удаления слушателей:

const controller = new AbortController();
const { signal } = controller;

document.addEventListener('keydown', (e) => {
  console.log('Нажата клавиша:', e.key);
}, { signal });

// Позже, когда обработчик больше не нужен:
controller.abort();

Ещё один важный момент — доступность. Не полагайтесь только на мышь. Пользователи с ограниченными возможностями могут работать только с клавиатуры. Убедитесь, что все интерактивные элементы доступны через Tab и активируются Enter или пробелом.

Что в итоге

Обработка событий клавиатуры и мыши — это фундамент любого интерактивного веб-приложения. Запомните главное: используйте делегирование, не забывайте про preventDefault и stopPropagation, следите за утечками памяти. И всегда думайте о пользователе: его действия должны быть предсказуемыми и удобными. Теперь вы знаете, как заставить интерфейс слушаться. Практикуйтесь, и всё получится.

Студия WNDER