Haunted — это современная библиотека для создания веб-компонентов на основе функциональных компонентов в стиле React, но с минимальным накладным кодом. Она использует Web Components API, позволяя создавать кастомные элементы с реактивным рендерингом и локальным состоянием. Основная цель Haunted — предоставить лёгкий и декларативный способ управления состоянием и жизненным циклом компонентов.
В 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));
Ключевые моменты:
html — функция шаблонов, аналог JSX, создаёт
виртуальный DOM.component — обёртка функции в полноценный Web
Component.useState — хук состояния, аналогичный React, возвращает
текущее значение и функцию для его обновления.@событие.Haunted предоставляет набор хуков, схожих с React:
Создаёт локальное состояние внутри компонента.
const [value, setValue] = useState(initialValue);
value — текущее значение состояния.setValue(newValue) — обновляет состояние и вызывает
повторный рендер.Позволяет выполнять побочные эффекты, например, подписки или запросы к API.
useEffect(() => {
const id = setInterval(() => console.log('tick'), 1000);
return () => clearInterval(id);
}, []);
Для более сложной логики состояния.
const [state, dispatch] = useReducer(reducer, initialState);
reducer — функция
(state, action) => newState.dispatch(action) — инициирует обновление
состояния.Haunted использует lit-html под капотом, что обеспечивает эффективное обновление DOM без полного перерендеринга:
return html`
<ul>
${items.map(item => html`<li>${item}</li>`)}
</ul>
`;
html и
автоматически отслеживается библиотекой.Свойства компонентов передаются как атрибуты или напрямую через объект props:
<my-counter initial="5"></my-counter>
Внутри компонента:
function Counter({ initial }) {
const [count, setCount] = useState(Number(initial));
}
Haunted автоматически следит за изменением свойств и повторно рендерит компонент при их обновлении.
Компоненты Haunted можно использовать друг внутри друга:
function Dashboard() {
return html`
<div>
<my-counter initial="10"></my-counter>
<my-counter initial="20"></my-counter>
</div>
`;
}
customElements.define('my-dashboard', component(Dashboard));
Haunted поддерживает Context API, позволяя передавать данные глубоко вниз по дереву компонентов без пропсов:
import { createContext, useContext } from 'haunted';
const ThemeContext = createContext('light');
function ThemedButton() {
const theme = useContext(ThemeContext);
return html`<button class=${theme}>Кнопка</button>`;
}
createContext создаёт контекст с дефолтным
значением.useContext позволяет компоненту получать текущее
значение.Компоненты Haunted могут реагировать на события нативно и через хуки:
<button @click=${() => alert('Clicked!')}>Нажми меня</button>
this.Haunted легко интегрируется с другими фреймворками и библиотеками:
import { html, component } from 'haunted';
import Chart from 'chart.js/auto';
function ChartComponent({ data }) {
let canvasRef;
useEffect(() => {
new Chart(canvasRef, { type: 'bar', data });
}, [data]);
return html`<canvas ${ref(canvasRef)}></canvas>`;
}
useEffect используется для инициализации сторонней
библиотеки.useMemo и useCallback.Haunted предоставляет лёгкую и мощную основу для разработки современных веб-компонентов с функциональной архитектурой и реактивным обновлением интерфейса, позволяя создавать масштабируемые проекты без лишнего кода.