Lit — современный фреймворк для создания веб-компонентов на JavaScript, предоставляющий удобные механизмы рендеринга и реактивности. Одним из ключевых аспектов разработки компонентов является обеспечение доступности (accessibility, a11y) и корректная работа с событиями.
Веб-доступность включает поддержку клавиатурной навигации, корректную работу с экранными считывателями и семантическую разметку. Lit позволяет создавать компоненты, соблюдающие эти требования, за счёт гибкой работы с атрибутами и свойствами.
Использование семантических элементов и ARIA-атрибутов
При создании пользовательских компонентов важно использовать правильные HTML-теги и ARIA-атрибуты для передачи состояния и роли элементов:
import { LitElement, html, css } from 'lit';
class AccessibleButton extends LitElement {
static properties = {
disabled: { type: Boolean }
};
static styles = css`
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
`;
render() {
return html`
<button
?disabled=${this.disabled}
aria-disabled=${this.disabled ? 'true' : 'false'}
role="button"
>
Нажми меня
</button>
`;
}
}
customElements.define('accessible-button', AccessibleButton);
В этом примере:
?disabled=${this.disabled} синхронизирует
состояние кнопки с DOM.aria-disabled передаёт состояние для скринридеров.role="button" уточняет семантику элемента, если она
отличается от стандартной кнопки.Клавиатурная навигация и фокус
Для интерактивных компонентов важно корректно управлять фокусом. Lit предоставляет методы для работы с Shadow DOM и прямой манипуляции DOM-элементами:
firstUpdated() {
this.button = this.renderRoot.querySelector('button');
}
focusButton() {
this.button.focus();
}
Поддержка клавиатуры требует обработки событий keydown и
keyup, чтобы реализовать стандартное поведение для Enter и
Space на кастомных кнопках:
_handleKeyDown(event) {
if (event.key === 'Enter' || event.key === ' ') {
this._triggerAction();
event.preventDefault();
}
}
Lit использует декларативную привязку событий через синтаксис
@event, что упрощает управление обработчиками и улучшает
читаемость кода.
Привязка событий в шаблоне
render() {
return html`
<button @click=${this._onClick}>Кликни меня</button>
`;
}
_onClick(event) {
console.log('Событие click:', event);
}
@click=${this._onClick} — привязка события к
обработчику.Кастомные события
Lit позволяет создавать и диспатчить кастомные события для взаимодействия компонентов между собой:
_handleAction() {
this.dispatchEvent(new CustomEvent('action-performed', {
detail: { message: 'Действие выполнено' },
bubbles: true,
composed: true
}));
}
detail передаёт дополнительные данные.bubbles позволяет событию всплывать по DOM.composed делает событие доступным за пределами Shadow
DOM.Обработка событий на уровне родителя
html`<accessible-button @action-performed=${this._onAction}></accessible-button>`
_onAction(event) {
console.log('Получено событие от дочернего компонента:', event.detail);
}
Важной практикой является синхронизация реактивных свойств компонента
с внешними событиями и атрибутами DOM. Например, изменение свойства
disabled должно автоматически обновлять атрибут и
визуальное состояние элемента. Lit обеспечивает это через систему
реактивных свойств и requestUpdate().
set disabled(value) {
const oldValue = this._disabled;
this._disabled = value;
this.requestUpdate('disabled', oldValue);
}
get disabled() {
return this._disabled;
}
Это позволяет компоненту корректно реагировать на внешние изменения и автоматически обновлять разметку, обеспечивая согласованность состояния и доступности.
Если компонент рендерит динамический контент, следует учитывать ARIA-live регионы для уведомления пользователей скринридеров о изменениях:
render() {
return html`
<div aria-live="polite">
${this._message}
</div>
`;
}
aria-live="polite" сообщает о нежных обновлениях, не
прерывая текущую работу пользователя.aria-live="assertive" используется для срочных
уведомлений.Использование таких практик обеспечивает не только корректную работу компонентов с событиями, но и высокую степень доступности интерфейсов.