Клавиатурная навигация является важным аспектом взаимодействия пользователя с веб-приложениями, особенно при работе с компонентами пользовательского интерфейса. Slim.js предоставляет гибкие возможности для организации работы с событиями клавиатуры, поддерживая декларативный и реактивный подход к обновлению интерфейса.
В Slim.js обработка событий клавиатуры осуществляется через
стандартные DOM-события keydown, keyup и
keypress. В компонентах Slim.js это можно сделать с помощью
директивы @event, которая связывает событие с методом
класса компонента:
import { Slim } from 'slim-js';
class KeyboardComponent extends Slim {
static get observedAttributes() {
return [];
}
constructor() {
super();
}
onKeyDown(event) {
if (event.key === 'ArrowUp') {
this.moveUp();
} else if (event.key === 'ArrowDown') {
this.moveDown();
}
}
moveUp() {
console.log('Навигация вверх');
}
moveDown() {
console.log('Навигация вниз');
}
get template() {
return Slim.html`
<div tabindex="0" @keydown="${this.onKeyDown}">
Навигация с клавиатуры
</div>
`;
}
}
customElements.define('keyboard-component', KeyboardComponent);
Ключевые моменты:
tabindex, чтобы получать фокус и
события клавиатуры.key, code, ctrlKey,
altKey и другие.Фокусировка элементов — основа клавиатурной навигации. В Slim.js для
управления фокусом используется стандартный DOM-метод
focus(). В сочетании с реактивными свойствами можно
динамически перемещать фокус между элементами:
moveDown() {
const nextElement = this.querySelector('.item.active')?.nextElementSibling;
if (nextElement) {
this.querySelector('.item.active')?.classList.remove('active');
nextElement.classList.add('active');
nextElement.focus();
}
}
Важные аспекты:
Tab и
навигацию стрелками.Slim.js не ограничивает стандартные возможности JavaScript для работы
с комбинациями клавиш. Можно проверять модификаторы (Ctrl,
Alt, Shift) и вызывать соответствующие
методы:
onKeyDown(event) {
if (event.ctrlKey && event.key === 's') {
event.preventDefault();
this.saveDocument();
}
}
saveDocument() {
console.log('Документ сохранен');
}
Особенности реализации:
event.preventDefault() предотвращает
стандартное поведение браузера.Для полноценной клавиатурной навигации необходимо учитывать
доступность компонентов. Использование атрибутов aria-*
помогает экранным читалкам корректно интерпретировать состояние
элементов:
<div role="menu" aria-orientation="vertical">
<div role="menuitem" tabindex="0">Пункт 1</div>
<div role="menuitem" tabindex="-1">Пункт 2</div>
</div>
role="menu" определяет контейнер как меню.tabindex="0" делает элемент фокусируемым.tabindex активного элемента.Slim.js поддерживает реактивные свойства, что позволяет автоматически обновлять интерфейс при изменении состояния фокусируемого элемента:
static get observedAttributes() {
return ['active-index'];
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'active-index') {
this.updateActiveItem(parseInt(newValue));
}
}
updateActiveItem(index) {
const items = this.querySelectorAll('.item');
items.forEach((item, i) => {
if (i === index) {
item.classList.add('active');
item.focus();
} else {
item.classList.remove('active');
}
});
}
Преимущества реактивного подхода:
ArrowUp и
ArrowDown.ArrowLeft и
ArrowRight.Ctrl+S,
Ctrl+Z).Для глобальной клавиатурной навигации можно использовать события на
document или window. В Slim.js это также можно
делать в методе connectedCallback:
connectedCallback() {
super.connectedCallback();
this._onGlobalKeyDown = this.onGlobalKeyDown.bind(this);
document.addEventListener('keydown', this._onGlobalKeyDown);
}
disconnectedCallback() {
document.removeEventListener('keydown', this._onGlobalKeyDown);
}
onGlobalKeyDown(event) {
if (event.key === 'Escape') {
this.closeMenu();
}
}
Slim.js позволяет комбинировать клавиатурную навигацию с другими реактивными механизмами, такими как привязка данных и динамическое создание элементов. Это делает возможным создание сложных интерфейсов, где фокус автоматически переходит между компонентами в зависимости от состояния приложения.