События клавиатуры: keydown, keyup
События
keydownиkeyupвозникают при нажатии и отпускании клавиши; они содержат информацию о нажатой клавише (key,code) и модификаторах (ctrlKey,shiftKey,altKey).
Зачем нужно
Обработка клавиатурных событий необходима для создания интерактивных интерфейсов: горячих клавиш, навигации с клавиатуры, игровых управлений, редакторов кода, форм с мгновенной обратной связью. Без них невозможна доступность (a11y) и удобство работы с приложением.
Где используется
- Горячие клавиши (Ctrl+S, Escape, Enter)
- Навигация по спискам стрелками
- Игры и интерактивные демо
- Автодополнение в полях ввода
- Закрытие модальных окон по Escape
Базовые события
| Событие | Когда | Повторяется при удержании |
|---|---|---|
keydown |
Клавиша нажата | Да |
keyup |
Клавиша отпущена | Нет |
keypress |
Устаревшее, не использовать | — |
document.addEventListener('keydown', (event) => {
console.log('key:', event.key); // 'a', 'Enter', 'ArrowLeft', ' '
console.log('code:', event.code); // 'KeyA', 'Enter', 'ArrowLeft', 'Space'
console.log('keyCode:', event.keyCode); // устаревшее, 65 для 'a'
});
key vs code
// key — символ или действие (зависит от раскладки и регистра)
// 'a', 'A', 'й', 'Й', 'Enter', 'ArrowUp', ' '
// code — физическая клавиша (не зависит от раскладки)
// 'KeyA', 'Enter', 'ArrowUp', 'Space', 'Digit1', 'F1'
// Для горячих клавиш используй code:
document.addEventListener('keydown', (e) => {
if (e.code === 'KeyS' && (e.ctrlKey || e.metaKey)) {
e.preventDefault();
save;
}
});
// Для ввода пользователем используй key:
input.addEventListener('keydown', (e) => {
if (e.key === 'Enter') submitForm;
});
Модификаторы
document.addEventListener('keydown', (e) => {
console.log({
ctrlKey: e.ctrlKey, // Ctrl (Windows/Linux) или Control (Mac)
metaKey: e.metaKey, // Cmd (Mac) или Win (Windows)
shiftKey: e.shiftKey, // Shift
altKey: e.altKey // Alt / Option
});
// Ctrl+Z или Cmd+Z (undo)
if ((e.ctrlKey || e.metaKey) && e.code === 'KeyZ') {
e.preventDefault();
undo;
}
// Shift+Enter — новая строка в чате
if (e.shiftKey && e.key === 'Enter') {
e.preventDefault();
insertNewline;
}
});
Навигация по списку стрелками
const items = document.querySelectorAll('.menu-item');
let activeIndex = 0;
document.addEventListener('keydown', (e) => {
switch (e.key) {
case 'ArrowDown':
e.preventDefault();
activeIndex = (activeIndex + 1) % items.length;
items[activeIndex].focus();
break;
case 'ArrowUp':
e.preventDefault();
activeIndex = (activeIndex - 1 + items.length) % items.length;
items[activeIndex].focus();
break;
case 'Escape':
closeMenu;
break;
case 'Enter':
items[activeIndex].click();
break;
}
});
Удержание клавиши (keydown repeat)
document.addEventListener('keydown', (e) => {
if (e.repeat) {
// Клавиша удерживается (keydown срабатывает повторно)
console.log('Удерживается:', e.key);
}
});
// Отслеживание нажатых клавиш для игр
const pressed = new Set();
document.addEventListener('keydown', (e) => pressed.add(e.code));
document.addEventListener('keyup', (e) => pressed.delete(e.code));
function gameLoop() {
if (pressed.has('ArrowLeft')) moveLeft;
if (pressed.has('ArrowRight')) moveRight;
requestAnimationFrame(gameLoop);
}
Частые ошибки
1. Использование keypress (устаревший)
// keypress не срабатывает для служебных клавиш (Delete, Arrow, F1...)
document.addEventListener('keypress', handler); // устаревший!
// Используй keydown для всего
document.addEventListener('keydown', handler);
2. Блокировка стандартного поведения без нужды
// Плохо: блокируем Copy/Paste
document.addEventListener('keydown', (e) => {
e.preventDefault(); // блокирует ВСЕ клавиши!
});
// Хорошо: блокируем только конкретную комбинацию
document.addEventListener('keydown', (e) => {
if (e.key === 'F5') e.preventDefault(); // запрет обновления
});
3. Зависимость от keyCode (устаревший)
// keyCode — устаревший, не используй
if (e.keyCode === 13) {} // плохо
// Современный способ:
if (e.key === 'Enter') {} // хорошо
if (e.code === 'Enter') {} // хорошо
Связанные темы
- События мыши -- click, mouseover, mouseenter
- События формы -- submit, input, change
- События фокуса -- focus, blur
- _MOC DOM
- _MOC JavaScript