DOM события клавиатуры и мыши
События клавиатуры и мыши — это механизм, позволяющий JavaScript реагировать на действия пользователя: нажатия клавиш, клики, наведение курсора и прокрутку.
Зачем нужно
Без обработки этих событий страница остаётся статичной. Именно через события клавиатуры и мыши реализуются интерактивные элементы: выпадающие меню, модальные окна, горячие клавиши, drag-and-drop, игровая логика и доступные компоненты. Понимание порядка событий (mousedown → mouseup → click) помогает избежать трудноуловимых багов.
Где используется
- Кнопки и ссылки (обработка
click) - Горячие клавиши и сочетания (Ctrl+S, Escape, Enter)
- Выпадающие меню (закрытие по клику вне, по Escape)
- Tooltip и hover-эффекты (
mouseenter/mouseleave) - Игровые интерфейсы (движение персонажа по
keydown) - Перетаскивание элементов (drag-and-drop через mouse-события)
Основной контент
Добавление обработчика
const btn = document.querySelector('#myBtn');
btn.addEventListener('click', (event) => {
console.log('Клик!', event);
});
// Удаление — нужна именованная функция
function handleClick(e) { console.log('click'); }
btn.addEventListener('click', handleClick);
btn.removeEventListener('click', handleClick);
События мыши
| Событие | Когда срабатывает |
|---|---|
click |
Нажатие и отпускание левой кнопки |
dblclick |
Двойной клик |
mousedown |
Кнопка мыши нажата |
mouseup |
Кнопка мыши отпущена |
mousemove |
Курсор движется |
mouseenter |
Курсор вошёл в элемент (не всплывает) |
mouseleave |
Курсор покинул элемент (не всплывает) |
mouseover |
Курсор над элементом или потомком (всплывает) |
contextmenu |
Правый клик / клавиша контекстного меню |
const card = document.querySelector('.card');
card.addEventListener('mouseenter', () => card.classList.add('hovered'));
card.addEventListener('mouseleave', () => card.classList.remove('hovered'));
card.addEventListener('mousemove', (e) => {
console.log(`Позиция: ${e.clientX}, ${e.clientY}`);
});
Координаты мыши
document.addEventListener('click', (e) => {
e.clientX; // от левого края viewport
e.clientY; // от верхнего края viewport
e.pageX; // от начала страницы (с учётом прокрутки)
e.pageY;
e.offsetX; // от левого края целевого элемента
e.offsetY;
});
События клавиатуры
| Событие | Когда срабатывает |
|---|---|
keydown |
Клавиша нажата (повторяется при удержании) |
keyup |
Клавиша отпущена |
keypress |
Устаревшее, не используйте |
document.addEventListener('keydown', (e) => {
console.log(e.key); // 'Enter', 'Escape', 'a', 'ArrowLeft'
console.log(e.code); // 'KeyA', 'Digit1', 'Space' (раскладка не влияет)
console.log(e.ctrlKey); // true если Ctrl зажат
console.log(e.shiftKey);
console.log(e.altKey);
console.log(e.metaKey); // Cmd на Mac
if (e.key === 'Escape') closeModal;
if (e.ctrlKey && e.key === 's') { e.preventDefault(); save; }
});
Делегирование событий
// Один обработчик на список вместо обработчика на каждый элемент
const list = document.querySelector('ul');
list.addEventListener('click', (e) => {
const item = e.target.closest('li');
if (!item) return;
console.log('Клик на:', item.textContent);
});
Прокрутка и колесо мыши
window.addEventListener('scroll', () => {
console.log(window.scrollY);
});
el.addEventListener('wheel', (e) => {
e.deltaY; // направление прокрутки колеса
});
Частые ошибки
- Используют
e.keyCodeилиe.which— оба устарели. Используйтеe.keyдля символа илиe.codeдля физической клавиши. - Вешают обработчик на каждый элемент в цикле — при большом количестве элементов это перегружает память. Используйте делегирование.
- Путают
mouseenterиmouseover—mouseoverвсплывает и срабатывает при наведении на потомков;mouseenterсрабатывает только для самого элемента. - Не вызывают
e.preventDefault()— для ссылок, кнопок отправки форм и горячих клавиш браузера нужно явно отменять поведение по умолчанию.