Haunted — это библиотека для создания веб-компонентов с реактивным подходом в стиле React, но с использованием нативных Web Components. Основная цель — предоставить простой способ управления состоянием и реактивностью без лишнего накладного кода.
Компоненты в Haunted создаются с помощью функции
component, которая принимает функцию с параметрами и
возвращает функцию, рендерящую шаблон:
import { component, html, useState } 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));
Ключевые моменты:
component(fn) превращает обычную функцию в Web
Component.html используется для шаблонов, аналогично JSX, но в
виде строк с интерполяцией.Haunted поддерживает передачу параметров через атрибуты HTML и свойства объекта. Атрибуты автоматически преобразуются в строки, поэтому для передачи сложных объектов лучше использовать свойства:
const el = document.createElement('my-counter');
el.initial = 10; // свойство
document.body.appendChild(el);
Особенности:
Для управления локальным состоянием применяется хук
useState:
const [value, setValue] = useState(0);
Подробности работы:
useState принимает начальное значение и возвращает
массив из текущего состояния и функции для его обновления.Haunted использует директиву @event для привязки
обработчиков:
html`<button @click=${increment}>Нажми меня</button>`
Особенности:
Параметры, переданные компоненту, автоматически отслеживаются:
function Greeting({ name }) {
return html`<p>Привет, ${name}!</p>`;
}
customElements.define('my-greeting', component(Greeting));
При изменении свойства name компонент перерендеривается
без дополнительного кода:
const greeting = document.querySelector('my-greeting');
greeting.name = 'Алексей';
Особенности:
Haunted поддерживает ES6 деструктуризацию и значения по умолчанию:
function UserCard({ user = { name: 'Гость', age: 0 } }) {
return html`<p>${user.name}, ${user.age} лет</p>`;
}
Преимущества:
Haunted предоставляет набор хуков для управления жизненным циклом и состоянием:
useState(initial) — локальное состояние.useEffect(callback, dependencies) — реакция на
изменения зависимостей.useRef(initial) — сохранение ссылки на элемент или
объект между рендерами.useReducer(reducer, initialState) — управление сложным
состоянием.Пример с useEffect:
import { useEffect } from 'haunted';
function Timer({ interval = 1000 }) {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => setCount(c => c + 1), interval);
return () => clearInterval(id);
}, [interval]);
return html`<p>Прошло: ${count} сек</p>`;
}
Особенности:
useEffect выполняется после рендера.Haunted полностью совместим с концепцией слотов Web Components:
function Card() {
return html`<div class="card"><slot></slot></div>`;
}
Применение:
<my-card>
<p>Содержимое карточки</p>
</my-card>
component(fn).useState.@event.Синтаксис Haunted сочетает простоту с мощью реактивного подхода, позволяя создавать легковесные и полностью нативные Web Components.