Haunted — это минималистичная библиотека для создания веб-компонентов на базе функциональных компонентов в стиле React, использующая стандарты Web Components. Одной из ключевых особенностей является работа с событиями и их интерфейсами, обеспечивающая гибкое взаимодействие компонентов и управление состоянием приложения.
В Haunted события обрабатываются через стандартный механизм DOM, но с
особенностями функционального подхода. Основной инструмент для привязки
событий — это атрибуты внутри шаблона, создаваемого с помощью
html из haunted.
import { html, component } from 'haunted';
function Counter({ count = 0 }) {
return html`
<div>
<p>Счетчик: ${count}</p>
<button @click=${() => count++}>Увеличить</button>
</div>
`;
}
customElements.define('my-counter', component(Counter));
Ключевое отличие от стандартного DOM в Haunted заключается в
использовании @event синтаксиса для привязки обработчиков.
Это упрощает работу с функциями внутри функциональных компонентов и
позволяет интегрировать их с реактивным состоянием через
useState.
Haunted полностью поддерживает кастомные события
(CustomEvent). Они создаются и отправляются стандартным
образом через dispatchEvent, а слушаются либо внутри
родительских компонентов, либо глобально.
function ChildComponent() {
const handleClick = () => {
const event = new CustomEvent('increment', { detail: 1, bubbles: true, composed: true });
this.dispatchEvent(event);
};
return html`<button @click=${handleClick}>Добавить</button>`;
}
customElements.define('child-component', component(ChildComponent));
Особое внимание стоит уделить свойствам bubbles и
composed. bubbles: true
позволяет событию подниматься по DOM-дереву, а
composed: true — проходить через Shadow
DOM, что критично для модульных компонентов, встроенных в закрытые
DOM-контейнеры.
Все события в Haunted наследуются от стандартного Event
DOM. Основные свойства и методы:
type — строка, указывающая тип события.target — элемент, на котором событие было изначально
вызвано.currentTarget — элемент, на котором обработчик события
был вызван.bubbles — булево значение, указывающее, всплывает ли
событие.cancelable — возможность отмены события с помощью
preventDefault().composedPath() — возвращает массив элементов, через
которые прошло событие.Для CustomEvent добавляется свойство
detail, содержащее произвольные данные, передаваемые вместе
с событием.
Haunted предлагает функциональные хуки для работы с событиями:
useEvent позволяет подписываться на события с
автоматическим управлением отпиской при размонтировании компонента.useState в связке с событиями обеспечивает реактивное
обновление интерфейса при их наступлении.Пример интеграции хуков:
import { html, component, useState } from 'haunted';
function ClickCounter() {
const [count, setCount] = useState(0);
const handleIncrement = (event) => {
setCount(count + event.detail);
};
return html`
<child-component @increment=${handleIncrement}></child-component>
<p>Итоговое значение: ${count}</p>
`;
}
customElements.define('click-counter', component(ClickCounter));
В данном примере событие increment обрабатывается через
реактивное состояние count, что полностью соответствует
концепции функционального подхода Haunted.
В Haunted компоненты по умолчанию создаются с Shadow DOM. Это накладывает ограничения на обработку событий:
composed: true, не могут
выйти из Shadow DOM.bubbles: false не всплывают даже
внутри Shadow DOM.composedPath() для правильной маршрутизации.Эти правила особенно важны при построении модульных интерфейсов с вложенными компонентами.
События в Haunted создают гибкую систему взаимодействия компонентов:
родитель может слушать события всех дочерних элементов, дочерние
компоненты могут уведомлять родителей о изменениях через
CustomEvent, а глобальные события можно использовать для
межкомпонентной коммуникации.
window.addEventListener('global-event', e => console.log(e.detail));
CustomEvent для передачи данных между
компонентами.bubbles: true и
composed: true для событий, которые должны быть видимы за
пределами Shadow DOM.disconnectedCallback, чтобы избежать утечек памяти.Интерфейсы событий в Haunted обеспечивают мощный, но при этом простой механизм связи компонентов через стандартный DOM API и кастомные расширения, позволяя создавать масштабируемые, реактивные приложения на Web Components.