Haunted — это библиотека для создания веб-компонентов на основе функционального подхода и Hooks, вдохновлённого React. Важным элементом взаимодействия компонентов между собой является CustomEvent API, стандартный механизм браузера для передачи событий с данными. Haunted интегрирует его естественным образом, позволяя компонентам создавать и слушать события без лишнего шума.
Для создания собственного события используется встроенный класс
CustomEvent. Основной синтаксис:
const event = new CustomEvent('имя_события', {
detail: данные, // передаваемые данные
bubbles: true, // всплытие события
composed: true // пересечение Shadow DOM
});
element.dispatchEvent(event);
detail — объект с произвольными
данными, которые будут доступны слушателям.bubbles — если true,
событие всплывает по DOM.composed — позволяет событию проходить
через Shadow DOM.В Haunted-компонентах элементом для диспатча обычно служит
root element, возвращаемый html
функцией.
import { html, component } from 'haunted';
function Counter() {
let count = 0;
const increment = () => {
count++;
const event = new CustomEvent('count-changed', {
detail: { count },
bubbles: true,
composed: true
});
this.dispatchEvent(event);
};
return html`
<button @click=${increment}>Увеличить: ${count}</button>
`;
}
customElements.define('my-counter', component(Counter));
В этом примере каждый клик по кнопке создаёт событие
count-changed, которое несёт текущий счёт.
Слушать события можно стандартным способом через
addEventListener. Haunted-компоненты позволяют использовать
это как на родительском элементе, так и внутри других компонентов.
const parent = document.querySelector('#parent');
parent.addEventListener('count-changed', (e) => {
console.log('Новое значение:', e.detail.count);
});
Особенности в Haunted:
composed: true позволяет событию проходить через Shadow
DOM, иначе событие может быть недоступно родителю.useEffect, позволяет
динамически подписываться на события внутри компонента.import { html, component, useEffect } from 'haunted';
function Logger() {
useEffect(() => {
const handler = (e) => console.log('Count обновлён:', e.detail.count);
window.addEventListener('count-changed', handler);
return () => window.removeEventListener('count-changed', handler);
}, []);
return html`<div>Слушатель запущен</div>`;
}
customElements.define('my-logger', component(Logger));
По умолчанию события внутри Shadow DOM не видны внешнему DOM. Чтобы
события могли всплывать через Shadow DOM, необходимо
устанавливать composed: true. Это ключевой момент при
работе с Haunted, поскольку компоненты по умолчанию создаются в Shadow
DOM:
const event = new CustomEvent('custom-action', { detail: { foo: 'bar' }, bubbles: true, composed: true });
this.dispatchEvent(event);
bubbles: true — позволяет событию
подниматься вверх по DOM.composed: true — позволяет событию
«выходить» из Shadow DOM, делая его доступным родительским
элементам.CustomEvent в Haunted часто применяется для связи нескольких компонентов без глобального состояния:
function ToggleButton() {
let active = false;
const toggle = () => {
active = !active;
this.dispatchEvent(new CustomEvent('toggle', { detail: { active }, bubbles: true, composed: true }));
};
return html`
<button @click=${toggle}>
${active ? 'Включено' : 'Выключено'}
</button>
`;
}
function StatusDisplay() {
useEffect(() => {
const handler = (e) => {
this.textContent = `Статус: ${e.detail.active ? 'Активен' : 'Неактивен'}`;
};
window.addEventListener('toggle', handler);
return () => window.removeEventListener('toggle', handler);
}, []);
return html`<div>Статус: Неизвестен</div>`;
}
В этом примере ToggleButton посылает событие, а StatusDisplay реагирует на него, обновляя своё отображение. Такой подход исключает необходимость использования глобального состояния, сохраняя функциональный подход Haunted.
Часто для удобства вытаскивают данные прямо из
detail:
element.addEventListener('count-changed', ({ detail: { count } }) => {
console.log('Текущее значение:', count);
});
Это упрощает чтение кода и делает обработчики событий более лаконичными.
bubbles и composed в
true, если событие должно быть доступно родительским
компонентам.detail можно
использовать объекты с описательными ключами.useEffect для подписки на события
предотвращает утечки памяти, автоматически удаляя слушатели при
размонтировании компонента.CustomEvent API в Haunted обеспечивает гибкую и безопасную передачу данных между компонентами, сохраняя декларативность и функциональный стиль, характерный для библиотеки. Его правильное использование позволяет строить сложные интерфейсы без лишней зависимости от внешних менеджеров состояния.