Фреймворк Lit предоставляет мощный и гибкий механизм работы с событиями в компонентах Web Components. Основная цель композиции событий — возможность корректно обрабатывать и передавать события через вложенные компоненты, сохраняя контекст и предотвращая нежелательное распространение.
В Lit компоненты создаются на основе класса, расширяющего
LitElement. Внутри компонентов события можно создавать и
слушать с использованием стандартного механизма DOM. Основные
моменты:
CustomEvent. Конструктор принимает два аргумента: тип
события и объект с настройками (detail,
bubbles, composed).this.dispatchEvent(new CustomEvent('my-event', {
detail: { message: 'Hello' },
bubbles: true,
composed: true
}));
bubbles: true позволяет событию подниматься по DOM
вверх.
composed: true делает событие доступным через Shadow
DOM.
Прослушивание события: В шаблоне компонента
события можно связывать с методами с помощью директивы
@eventName.
html`<button @click=${this.handleClick}>Нажми меня</button>`
При построении сложных интерфейсов часто возникает необходимость
передавать события через несколько уровней компонентов. Lit позволяет
это сделать через правильную настройку bubbles и
composed:
bubbles: true и composed: true.Пример:
class InnerComponent extends LitElement {
render() {
return html`<button @click=${this._onClick}>Click</button>`;
}
_onClick() {
this.dispatchEvent(new CustomEvent('inner-click', {
detail: { info: 'clicked inside' },
bubbles: true,
composed: true
}));
}
}
customElements.define('inner-component', InnerComponent);
class OuterComponent extends LitElement {
render() {
return html`<inner-component @inner-click=${this._handleInnerClick}></inner-component>`;
}
_handleInnerClick(e) {
console.log(e.detail.info); // 'clicked inside'
}
}
customElements.define('outer-component', OuterComponent);
Иногда необходимо, чтобы компонент не только обрабатывал событие, но
и передавал его дальше с модификацией. Это реализуется через повторный
dispatchEvent:
_handleInnerClick(e) {
const newDetail = { ...e.detail, additional: 'extra info' };
this.dispatchEvent(new CustomEvent('outer-click', {
detail: newDetail,
bubbles: true,
composed: true
}));
}
Этот подход позволяет строить цепочки событий, где каждый уровень может добавлять или изменять данные события, не нарушая базовую обработку.
Важно различать stopPropagation и
stopImmediatePropagation. В Lit их использование идентично
стандартному DOM, но следует помнить:
e.stopPropagation() останавливает всплытие события на
верхние уровни, но другие слушатели на том же элементе сработают.e.stopImmediatePropagation() блокирует также другие
обработчики на том же элементе.Правильное использование этих методов позволяет управлять сложными цепочками событий, предотвращая конфликты.
Для более сложной логики возможна обработка нескольких событий в
одном компоненте. В Lit удобно использовать комбинацию
@event директив и методов с динамической маршрутизацией
данных.
html`
<inner-component @inner-click=${this._handleInnerClick}></inner-component>
<another-component @another-event=${this._handleAnotherEvent}></another-component>
`
Внутри методов можно объединять данные из разных источников и создавать новые события, формируя централизованное управление состоянием.
composedБез composed: true событие не выйдет за пределы Shadow
DOM. Это критично при построении крупных приложений с вложенными
компонентами, где верхний уровень должен реагировать на действия внутри
внутреннего компонента.
this.dispatchEvent(new CustomEvent('event-name', {
detail: {},
bubbles: true,
composed: false // событие останется внутри Shadow DOM
}));
Использование composed: true обеспечивает «сквозное»
распространение событий через Shadow DOM, что является стандартной
практикой при композиции.
bubbles: true
и composed: true, если их предполагается обрабатывать на
внешних компонентах.window или
document без необходимости, чтобы не нарушать локальность
компонентов.dispatchEvent для изменения
данных события без нарушения цепочки.Композиция событий в Lit обеспечивает гибкое и безопасное взаимодействие между компонентами, позволяя строить сложные интерфейсы с прозрачной передачей данных через Shadow DOM и обычный DOM. Это фундаментальный инструмент при создании масштабируемых приложений на основе Web Components.