Haunted — это библиотека для создания веб-компонентов на основе стандартного API Custom Elements с использованием реактивного подхода, вдохновлённого React Hooks. Она позволяет создавать динамические интерфейсы без необходимости подключать полноценный фреймворк, оставляя разработчику контроль над жизненным циклом компонентов и производительностью. Ключевое отличие Haunted — это использование функциональных компонентов и хуков вместо классовых компонентов, характерных для стандартного Web Components API.
Функциональный компонент в Haunted представляет собой функцию,
возвращающую шаблон HTML, созданный с помощью библиотеки
lit-html. Пример базового компонента:
import { html, render } from 'lit-html';
import { 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 — создаёт локальное состояние компонента.component — обёртка для функции, превращающая её в
полноценный веб-компонент.@click) можно напрямую привязывать к функциям
внутри компонента.Web Components традиционно создаются через классы,
наследуемые от HTMLElement, с методами жизненного цикла
(connectedCallback, disconnectedCallback,
attributeChangedCallback). Haunted упрощает этот процесс,
позволяя отказаться от классов и использовать привычный функциональный
стиль.
Пример нативного подхода:
class CounterElement extends HTMLElement {
constructor() {
super();
this.count = 0;
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
this.render();
this.shadowRoot.querySelector('button')
.addEventListener('click', () => {
this.count++;
this.render();
});
}
render() {
this.shadowRoot.innerHTML = `
<div>
<p>Счётчик: ${this.count}</p>
<button>Увеличить</button>
</div>
`;
}
}
customElements.define('native-counter', CounterElement);
Различия:
Haunted часто сравнивают с React, так как оба используют виртуальный DOM и хуки, но есть принципиальные различия:
ReactDOM.render, тогда
как Haunted рендерит шаблоны напрямую через lit-html.useEffect, useState и др.) в функциональных
компонентах, что делает код более декларативным и приближает к
React-хукам, но с меньшим накладным весом.Lit — это библиотека для упрощения создания Web Components с декларативным шаблонированием и реактивностью через свойства. Haunted дополняет этот подход, добавляя функциональный стиль и хуки.
| Особенность | Haunted | Lit / LitElement |
|---|---|---|
| Стиль компонентов | Функциональный | Классовый |
| Реактивность | Через хуки (useState) |
Через свойства и @property |
| Интеграция с DOM | Нативный Web Component | Нативный Web Component |
| Поддержка JSX | Нет (только lit-html) | Нет (lit-html) |
| Размер сборки | Минимальный | Средний |
Главное отличие Haunted — это упрощение синтаксиса и возможность использовать привычные React-подобные паттерны без полной зависимости от React или сложного класса LitElement.
Haunted поддерживает стандартные хуки:
useState — управление локальным состоянием.useEffect — реагирование на изменения состояния или
жизненного цикла компонента.useRef — хранение ссылок на DOM-элементы без повторного
рендера.useReducer — для более сложного управления состоянием,
аналог Redux-подхода.Пример использования useEffect:
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));
Хук useEffect здесь полностью заменяет необходимость в
connectedCallback и disconnectedCallback,
делая код более компактным и декларативным.
Haunted легко интегрируется с любыми библиотеками, работающими с DOM:
D3, Three.js, Chart.js и даже React-компонентами через wrapper. В
отличие от React, нет необходимости оборачивать все в
ReactDOM.createRoot. Это делает Haunted подходящим для
постепенной миграции существующих проектов или
микрофронтенд-структур.
Haunted сочетает преимущества функциональных компонентов и хуков с нативными Web Components, минимизируя объем зависимостей и повышая производительность. По сравнению с классическим Web Components, упрощает работу с состоянием и событиями. В сравнении с React и Lit, предлагает легковесную альтернативу с нативной интеграцией и реактивностью, сохраняя декларативный стиль разработки и гибкость для сложной логики компонентов.