Lit — современный фреймворк для создания веб-компонентов на базе стандарта Web Components. Ключевой аспект работы с веб-компонентами — это система событий, которая обеспечивает взаимодействие между компонентами и внешним миром. События позволяют компоненту уведомлять о своих изменениях, действиях пользователя или внутренних состояниях.
В стандартном DOM события делятся на два типа: события с фазой всплытия (bubbling) и события с фазой перехвата (capturing). В Lit эти механизмы полностью сохраняются:
Для создания кастомного события используется конструктор
CustomEvent:
this.dispatchEvent(new CustomEvent('my-event', {
detail: { value: 42 },
bubbles: true,
composed: true
}));
Ключевые параметры:
true, событие всплывает
вверх по DOM.true, событие может
пересекать границу Shadow DOM. Это особенно важно для Lit, так как
большинство компонентов используют Shadow DOM для инкапсуляции.В Lit обработчики событий привязываются к элементам через синтаксис шаблона:
import { LitElement, html } from 'lit';
class MyComponent extends LitElement {
handleClick(e) {
console.log('Клик по компоненту', e.detail);
}
render() {
return html`
<button @click=${this.handleClick}>Нажми меня</button>
`;
}
}
customElements.define('my-component', MyComponent);
Особенности:
@ перед именем события используется для привязки
события DOM к методу класса..bind(this) при необходимости.Для передачи данных от дочернего компонента к родительскому используются кастомные события:
class ChildComponent extends LitElement {
notifyParent() {
this.dispatchEvent(new CustomEvent('child-updated', {
detail: { message: 'Данные обновлены' },
bubbles: true,
composed: true
}));
}
render() {
return html`<button @click=${this.notifyParent}>Обновить родителя</button>`;
}
}
customElements.define('child-component', ChildComponent);
На родительском элементе можно обработать это событие так:
class ParentComponent extends LitElement {
handleChildUpdate(e) {
console.log('Событие от дочернего компонента:', e.detail.message);
}
render() {
return html`
<child-component @child-updated=${this.handleChildUpdate}></child-component>
`;
}
}
customElements.define('parent-component', ParentComponent);
Особенности, которые важно учитывать:
detail позволяет передавать любые данные
без прямого доступа к внутреннему состоянию компонента.Lit поддерживает реактивные свойства через декоратор
@property. Изменение таких свойств может быть связано с
генерацией событий:
import { LitElement, html } from 'lit';
import { property } from 'lit/decorators.js';
class ReactiveComponent extends LitElement {
@property({ type: Number })
count = 0;
increment() {
this.count++;
this.dispatchEvent(new CustomEvent('count-changed', {
detail: { count: this.count },
bubbles: true,
composed: true
}));
}
render() {
return html`
<button @click=${this.increment}>Увеличить счетчик</button>
<p>Текущее значение: ${this.count}</p>
`;
}
}
customElements.define('reactive-component', ReactiveComponent);
Реактивные свойства автоматически обновляют DOM при изменении, а кастомные события позволяют синхронизировать состояние с другими компонентами.
Для оптимизации часто используется делегирование событий, когда один обработчик на родительском элементе обрабатывает события от нескольких дочерних элементов. В Lit это может выглядеть так:
render() {
return html`
<div @click=${this.handleClick}>
<button data-action="save">Сохранить</button>
<button data-action="delete">Удалить</button>
</div>
`;
}
handleClick(e) {
const action = e.target.dataset.action;
if (action) {
console.log('Действие:', action);
}
}
Преимущества:
Lit предоставляет дополнительные хуки, которые не являются стандартными событиями DOM, но позволяют реагировать на изменения состояния компонента:
connectedCallback — вызывается при добавлении элемента
в DOM.disconnectedCallback — вызывается при удалении элемента
из DOM.updated(changedProperties) — вызывается после
обновления реактивных свойств.firstUpdated(changedProperties) — вызывается после
первого рендера компонента.Использование этих методов совместно с dispatchEvent
позволяет создавать сложные и гибкие схемы событийной коммуникации между
компонентами.
composed: true для
событий, которые должны достигать внешнего DOM.detail)
для передачи данных вместо прямого доступа к свойствам.Система событий в Lit сочетает возможности стандартного DOM с удобной реактивной моделью, обеспечивая гибкую коммуникацию между компонентами и позволяя создавать сложные интерфейсы без утраты инкапсуляции.