Haunted — это легковесная библиотека для создания веб-компонентов на основе реактивного подхода, вдохновленного React Hooks. Она сочетает преимущества нативных веб-компонентов и удобство реактивного управления состоянием. Взаимодействие компонентов в Haunted строится на нескольких ключевых паттернах, позволяющих управлять состоянием, потоками данных и событиями эффективно и предсказуемо.
Компоненты Haunted получают входные данные через свойства (props). Свойства позволяют компоненту быть переиспользуемым и независимым.
import { html, component } from 'haunted';
function MyButton({ label, onClick }) {
return html`<button @click=${onClick}>${label}</button>`;
}
customElements.define('my-button', component(MyButton));
Ключевые моменты:
Для управления внутренним состоянием компонентов используется хук
useState. Он обеспечивает реактивность и гарантирует, что
изменения состояния обновляют только конкретный компонент.
import { html, component, useState } from 'haunted';
function Counter() {
const [count, setCount] = useState(0);
return html`
<div>
<p>Счёт: ${count}</p>
<button @click=${() => setCount(count + 1)}>Увеличить</button>
</div>
`;
}
customElements.define('my-counter', component(Counter));
Особенности использования:
useState можно вызывать несколько раз для управления
различными частями состояния.useEffect позволяет реагировать на изменения состояния,
свойств или выполнение побочных эффектов, аналогично React.
import { useEffect, useState, html, component } from 'haunted';
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => setSeconds(s => s + 1), 1000);
return () => clearInterval(interval);
}, []);
return html`<p>Прошло секунд: ${seconds}</p>`;
}
customElements.define('my-timer', component(Timer));
Особенности:
[] задаёт зависимости эффекта. Пустой
массив означает выполнение эффекта только при монтировании.Haunted не ограничивает механизмами только внутреннее состояние. Для связи компонентов друг с другом используются кастомные события.
function ChildComponent({ onNotify }) {
return html`<button @click=${() => onNotify('данные от ребёнка')}>Отправить</button>`;
}
function ParentComponent() {
const handleNotify = (message) => console.log('Сообщение:', message);
return html`<child-component .onNot ify=${handleNotify}></child-component>`;
}
customElements.define('parent-component', component(ParentComponent));
customElements.define('child-component', component(ChildComponent));
Особенности взаимодействия:
dispatchEvent с
CustomEvent, чтобы компонент оставался независимым
и изолированным.Haunted поддерживает создание контекста, позволяющего делиться данными между компонентами без передачи свойств через все уровни иерархии.
import { provide, consume } from 'haunted';
const ThemeContext = Symbol('theme');
function ThemeProvider({ theme, children }) {
provide(ThemeContext, theme);
return html`${children}`;
}
function ThemedButton() {
const theme = consume(ThemeContext);
return html`<button style="background:${theme.background}; color:${theme.color}">Кнопка</button>`;
}
Особенности:
Для предотвращения лишних рендеров в Haunted используется
useMemo и useCallback.
import { useMemo, html, component } from 'haunted';
function ExpensiveCalculation({ value }) {
const result = useMemo(() => {
console.log('Вычисление...');
return value ** 2;
}, [value]);
return html`<p>Результат: ${result}</p>`;
}
Особенности:
useMemo кэширует вычисления между рендерами, если
зависимости не изменились.useCallback сохраняет функции, предотвращая их
пересоздание, что особенно важно при передаче функций в дочерние
компоненты.Haunted позволяет интегрироваться с асинхронными потоками, включая RxJS, Promises или собственные подписки.
import { useEffect, useState, html, component } from 'haunted';
function DataFetcher({ url }) {
const [data, setData] = useState(null);
useEffect(() => {
let cancelled = false;
fetch(url)
.then(res => res.json())
.then(json => !cancelled && setData(json));
return () => { cancelled = true; };
}, [url]);
return html`<pre>${JSON.stringify(data, null, 2)}</pre>`;
}
Особенности:
useState и useEffect,
компоненты остаются чистыми и предсказуемыми.Эти паттерны создают прочную основу для построения сложных интерфейсов в Haunted, обеспечивая реактивность, переиспользуемость и чистое взаимодействие компонентов. Они позволяют масштабировать приложения, сохраняя ясную структуру данных и управление состоянием.