Haunted — это библиотека для создания веб-компонентов на базе стандартов Custom Elements и функционального подхода, вдохновлённая React Hooks. Основная цель Haunted — упрощение написания реактивного UI без необходимости использования классов и сложных жизненных циклов, предоставляя лёгкий, модульный и декларативный подход.
В Haunted основной единицей является функциональный
компонент, который представляет собой обычную
JavaScript-функцию. Она принимает props и возвращает
template literal с HTML-разметкой, используя встроенную
функцию html из Haunted.
import { html, component } from 'haunted';
function MyButton({ label, onClick }) {
return html`
<button @click=${onClick}>${label}</button>
`;
}
customElements.define('my-button', component(MyButton));
Ключевые моменты:
component(MyButton) превращает обычную функцию в
полноценный веб-компонент.@event,
аналогичного Lit.Haunted предоставляет набор хуков, аналогичных React, для управления состоянием и побочными эффектами.
import { useState } from 'haunted';
function Counter() {
const [count, setCount] = useState(0);
return html`
<div>
<p>Счётчик: ${count}</p>
<button @click=${() => setCount(count + 1)}>Увеличить</button>
</div>
`;
}
import { useEffect } from 'haunted';
function Logger({ message }) {
useEffect(() => {
console.log('Сообщение изменилось:', message);
}, [message]);
return html`<p>${message}</p>`;
}
import { useRef } from 'haunted';
function FocusInput() {
const inputRef = useRef();
return html`
<input ref=${inputRef} />
<button @click=${() => inputRef.current.focus()}>Фокус</button>
`;
}
Особенности хуков в Haunted:
useEffect позволяет
контролировать вызовы побочных эффектов.Haunted поддерживает вложенные компоненты и композицию, что позволяет строить сложные интерфейсы из мелких модулей.
function App() {
return html`
<div>
<my-button label="Клик" @click=${() => alert('Нажато')} />
<counter-component></counter-component>
</div>
`;
}
component() и использовать как обычный HTML-тег.Haunted скрывает большую часть сложности классов, но всё ещё предоставляет доступ к жизненному циклу через хуки:
useEffect без зависимостей выполняется после каждого
рендера.useEffect с пустым массивом выполняется один раз при
монтировании компонента.useEffect с возвращаемой функцией позволяет реализовать
очистку ресурсов при размонтировании.useEffect(() => {
const id = setInterval(() => console.log('Таймер'), 1000);
return () => clearInterval(id); // очистка при размонтировании
}, []);
Haunted не накладывает строгой системы стилей. Возможны несколько подходов:
return html`
<button style="background: blue; color: white;">Нажми</button>
`;
<style> внутри
шаблона:return html`
<style>
button { background: green; color: white; padding: 8px; }
</style>
<button>Кнопка</button>
`;
component()
обеспечивает инкапсуляцию стилей.Haunted минимизирует перерисовку, но есть дополнительные техники:
useState.useMemo для вычислений,
зависящих от props или state.Haunted совместим с ES Modules, что позволяет подключать библиотеку напрямую:
<script type="module">
import { html, component } from 'https://unpkg.com/haunted/haunted.js?module';
</script>
Для сборки через bundler (Webpack, Vite, Rollup) достаточно установить через npm:
npm install haunted
и импортировать функции из пакета.
Haunted сочетает преимущества функционального подхода и стандарта веб-компонентов, позволяя строить реактивные, компактные и легко тестируемые интерфейсы. Использование хуков и template literals делает разработку удобной и предсказуемой, а композиция компонентов обеспечивает масштабируемость больших приложений.