В Stencil, как и в большинстве современных фреймворков, важным
элементом архитектуры являются пользовательские события. Эти события
позволяют компонентам взаимодействовать друг с другом, реагировать на
действия пользователя и уведомлять другие части приложения о различных
изменениях состояния. Для работы с такими событиями в Stencil
используется декоратор @Event.
Декоратор @Event в Stencil применяется к методам
компонентов и позволяет определить пользовательские события, которые
могут быть переданы родительскому компоненту или любому другому
компоненту, подписанному на это событие. Это важно для реализации
однонаправленного потока данных и поддержания хорошей архитектуры.
Применение декоратора @Event выглядит следующим
образом:
import { Component, h, Event, EventEmitter } from '@stencil/core';
@Component({
tag: 'my-button',
styleUrl: 'my-button.css',
shadow: true
})
export class MyButton {
@Event() buttonClicked: EventEmitter<void>;
handleClick() {
this.buttonClicked.emit();
}
render() {
return (
<button onCl ick={() => this.handleClick()}>Click me!</button>
);
}
}
В этом примере компонент my-button создает событие
buttonClicked с помощью декоратора @Event.
Метод handleClick вызывает emit() для отправки
этого события. Это событие теперь может быть перехвачено родительским
компонентом.
Каждое событие, создаваемое с помощью @Event, является
экземпляром EventEmitter. Этот объект предоставляет методы
для эмитации событий и их подписки. Кроме того,
EventEmitter поддерживает передачу данных вместе с
событием, что позволяет отправлять дополнительные параметры при его
возникновении.
Пример с передачей данных:
import { Component, h, Event, EventEmitter } from '@stencil/core';
@Component({
tag: 'my-button',
styleUrl: 'my-button.css',
shadow: true
})
export class MyButton {
@Event() buttonClicked: EventEmitter<string>;
handleClick() {
this.buttonClicked.emit('Hello from my-button!');
}
render() {
return (
<button onCl ick={() => this.handleClick()}>Click me!</button>
);
}
}
В этом случае событие buttonClicked будет отправлять
строку с сообщением при каждом клике.
Для того чтобы другие компоненты могли прослушивать события, они должны подписаться на соответствующие события с помощью обычного подхода к обработке событий в DOM.
Пример компонента-родителя, который прослушивает событие
buttonClicked от дочернего компонента:
import { Component, h } from '@stencil/core';
@Component({
tag: 'parent-component',
styleUrl: 'parent-component.css',
shadow: true
})
export class ParentComponent {
handleButtonClick(event: CustomEvent<string>) {
console.log(event.detail); // 'Hello from my-button!'
}
render() {
return (
<my-button onButtonClic ked={event => this.handleButtonClick(event)}></my-button>
);
}
}
Здесь компонент parent-component прослушивает событие
buttonClicked, получая данные, передаваемые дочерним
компонентом. С помощью события onButtonClicked можно
привязать обработчик события, который будет вызван при его
возникновении.
CustomEventПоскольку Stencil использует стандартный механизм событий браузера,
пользовательские события, созданные через @Event, являются
экземплярами CustomEvent. Это означает, что в обработчике
события можно получить доступ к объекту detail, в котором
содержится дополнительная информация, переданная вместе с событием. Это
может быть строка, объект или даже массив, в зависимости от того, что
было передано в метод emit.
Пример передачи объекта:
import { Component, h, Event, EventEmitter } from '@stencil/core';
@Component({
tag: 'my-button',
styleUrl: 'my-button.css',
shadow: true
})
export class MyButton {
@Event() buttonClicked: EventEmitter<object>;
handleClick() {
this.buttonClicked.emit({ message: 'Data sent from button!' });
}
render() {
return (
<button onCl ick={() => this.handleClick()}>Click me!</button>
);
}
}
В этом примере событие отправляет объект с полем
message. Родительский компонент может получить доступ к
этому объекту через event.detail.
События с одинаковыми именами: В отличие от обычных событий DOM, события Stencil с одинаковыми именами не будут конфликтовать, если они находятся в разных компонентах. Это возможно благодаря использованию в Stencil уникальных пространств имен для событий, что гарантирует отсутствие пересечений.
Работа с асинхронными событиями: События могут быть использованы для асинхронных операций. Например, при отправке данных на сервер или обработке крупных вычислений можно отправлять промежуточные события, которые будут уведомлять другие компоненты о ходе выполнения.
Модификаторы событий: В Stencil поддерживаются
стандартные модификаторы событий, такие как bubbles,
cancelable и другие. Эти параметры могут быть заданы при
создании события, определяя его поведение при всплытии или
отмене.
Пример с модификаторами:
import { Component, h, Event, EventEmitter } from '@stencil/core';
@Component({
tag: 'my-button',
styleUrl: 'my-button.css',
shadow: true
})
export class MyButton {
@Event({
bubbles: true,
cancelable: true
}) buttonClicked: EventEmitter<void>;
handleClick() {
this.buttonClicked.emit();
}
render() {
return (
<button onCl ick={() => this.handleClick()}>Click me!</button>
);
}
}
В этом примере событие buttonClicked будет всплывать по
дереву DOM и его можно будет отменить, если это необходимо.
Декоратор @Event в Stencil предоставляет мощные
возможности для работы с пользовательскими событиями. Он позволяет
создавать события, которые могут передавать данные между компонентами, и
делает возможным гибкую настройку их поведения через параметры
модификаторов. Использование @Event позволяет строить
компоненты с четким разделением ответственности и упрощает архитектуру
приложения.