Haunted — это библиотека для создания веб-компонентов на основе реактивного программирования в стиле Hooks, вдохновлённого React. Основной акцент делается на легковесность, композицию функций и повторное использование логики. В отличие от стандартных веб-компонентов, Haunted позволяет строить сложные интерфейсы, используя чистые функции и хуки, без необходимости наследовать HTMLElement и управлять жизненным циклом вручную.
Функциональный компонент в Haunted — это обычная JavaScript-функция,
возвращающая шаблон разметки, создаваемой с помощью html
(из haunted):
import { html, component } from 'haunted';
function Counter({ initial = 0 }) {
const [count, setCount] = useState(initial);
return html`
<div>
<p>Счётчик: ${count}</p>
<button @click=${() => setCount(count + 1)}>Увеличить</button>
</div>
`;
}
customElements.define('my-counter', component(Counter));
Ключевые моменты:
useState создаёт реактивное состояние внутри
компонента.component() оборачивает функцию в веб-компонент,
автоматически управляя обновлением DOM при изменении состояния.html используется для шаблонов с динамическим
содержимым.Haunted делает возможной глубокую композицию компонентов, где один компонент может содержать другой:
function App() {
return html`
<div>
<h1>Главный интерфейс</h1>
<my-counter initial="5"></my-counter>
<my-counter initial="10"></my-counter>
</div>
`;
}
customElements.define('my-app', component(App));
Особенности:
Haunted поддерживает создание кастомных хуков, что позволяет инкапсулировать повторяемую реактивную логику:
function useCounter(initial = 0) {
const [count, setCount] = useState(initial);
const increment = () => setCount(count + 1);
const decrement = () => setCount(count - 1);
return { count, increment, decrement };
}
function CounterControls() {
const { count, increment, decrement } = useCounter(3);
return html`
<div>
<button @click=${decrement}>-</button>
<span>${count}</span>
<button @click=${increment}>+</button>
</div>
`;
}
customElements.define('counter-controls', component(CounterControls));
Паттерн повторного использования логики:
Haunted предоставляет возможность реактивного обновления компонентов при изменении атрибутов:
function Greeting({ name }) {
return html`<p>Привет, ${name}!</p>`;
}
customElements.define('greeting-element', component(Greeting));
name автоматически вызовет
перерендер.Расширенные техники:
useEffect для выполнения побочных
эффектов при изменении props или состояния.Haunted интегрируется с нативной системой слотов веб-компонентов, позволяя композицию пользовательской разметки:
function Card({ title }) {
return html`
<div class="card">
<h2>${title}</h2>
<slot></slot>
</div>
`;
}
customElements.define('custom-card', component(Card));
<slot> обеспечивает вставку произвольного
контента внутрь компонента.Для повторного применения логики компонентов можно создавать функции-обертки, которые возвращают готовый компонент:
function withBorder(Component) {
return function(props) {
return html`<div style="border: 2px solid black; padding: 10px;">
<${Component} ...=${props}></${Component}>
</div>`;
};
}
const BorderedCounter = withBorder(Counter);
customElements.define('bordered-counter', component(BorderedCounter));
Haunted ориентирован на чистый функциональный подход, где каждая часть интерфейса может быть отдельно протестирована, переиспользована и легко комбинируется с другими компонентами без громоздкой инфраструктуры.