Haunted — это современная библиотека для создания веб-компонентов на основе Web Components и реактивного подхода, похожего на React Hooks. Одним из ключевых аспектов управления состоянием в сложных компонентах является диспатч действий. В Haunted этот механизм реализован через кастомные события и реактивные обновления, что позволяет отделять логику состояния от отображения.
dispatch и кастомных событийВ Haunted компонент может инициировать изменения
состояния через функцию dispatch, которая, по
сути, создает и отправляет кастомное событие. События
могут быть перехвачены родительскими компонентами или любыми
слушателями, что обеспечивает гибкую архитектуру.
Пример базового диспатча:
import { html, component, useState } from 'haunted';
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
const event = new CustomEvent('increment', {
detail: { value: count + 1 },
bubbles: true,
composed: true
});
dispatchEvent(event);
};
return html`
<div>
<p>Счётчик: ${count}</p>
<button @click=${increment}>Увеличить</button>
</div>
`;
}
customElements.define('my-counter', component(Counter));
Ключевые моменты:
CustomEvent позволяет передать данные через
detail.bubbles: true и composed: true
обеспечивают, что событие поднимется через
DOM-иерархию, позволяя родительскому компоненту его
обработать.dispatchEvent вызывается на текущем элементе
(this), что делает компонент автономным и независимым.Родительские компоненты могут слушать события и обновлять состояние или выполнять другие действия. Это особенно важно при использовании Haunted для создания приложений с несколькими связанными компонентами.
import { html, component, useState } from 'haunted';
import './counter.js';
function App() {
const [total, setTotal] = useState(0);
const handleIncrement = (event) => {
setTotal(event.detail.value);
};
return html`
<div @increment=${handleIncrement}>
<my-counter></my-counter>
<p>Общее значение: ${total}</p>
</div>
`;
}
customElements.define('my-app', component(App));
Особенности подхода:
Haunted предоставляет стандартные хуки, такие как
useState и useEffect, которые можно
использовать для реактивного обновления при диспатче
событий.
import { html, component, useState, useEffect } from 'haunted';
function Logger() {
const [logs, setLogs] = useState([]);
useEffect(() => {
const logEvent = (e) => setLogs(prev => [...prev, e.detail.value]);
window.addEventListener('increment', logEvent);
return () => window.removeEventListener('increment', logEvent);
}, []);
return html`
<ul>
${logs.map(log => html`<li>${log}</li>`)}
</ul>
`;
}
customElements.define('event-logger', component(Logger));
useEffect позволяет подписываться и
отписываться от событий автоматически.Важно понимать, что detail кастомного события — это
едиственный безопасный способ передавать данные между
компонентами в Haunted. Любые попытки напрямую менять состояние родителя
нарушают инкапсуляцию.
const event = new CustomEvent('update-user', {
detail: { name: 'Alice', age: 25 },
bubbles: true,
composed: true
});
this.dispatchEvent(event);
detail позволяет содержать
структурированную информацию.Централизованный менеджер событий Использовать один контейнер, который собирает и распределяет события от всех дочерних компонентов. Это помогает поддерживать единое состояние приложения без глобального хранилища.
Именованные события Присваивать событиям
уникальные имена (increment-user,
delete-item), чтобы избежать конфликтов и случайного
перехвата.
Композиция компонентов Диспатч действий позволяет строить сложные компоненты из более мелких, при этом не теряя контроля над состоянием и не создавая жёстких связей между компонентами.
Haunted можно использовать совместно с Redux, MobX или Zustand. В
таком случае dispatch может быть обёрнут в вызовы
экшенов:
const increment = () => {
store.dispatch({ type: 'INCREMENT', payload: count + 1 });
};
Диспатч действий в Haunted — это мощный инструмент для построения реактивной, модульной архитектуры веб-компонентов, обеспечивающий чистое разделение логики и отображения, а также гибкость при взаимодействии между компонентами.