Haunted — это современная библиотека для создания веб-компонентов на базе стандартов Custom Elements и Shadow DOM с использованием реактивного подхода, похожего на React Hooks. Она обеспечивает лёгкую интеграцию компонентов в любой проект без необходимости подключения больших фреймворков. Главная цель Haunted — сделать реактивные веб-компоненты максимально простыми, гибкими и совместимыми с нативным DOM.
Компонент в Haunted создаётся как функция, возвращающая разметку с
помощью html тег-функции. Основная структура компонента
выглядит следующим образом:
import { html, component } from 'haunted';
function MyComponent({ name }) {
return html`<p>Привет, ${name}!</p>`;
}
customElements.define('my-component', component(MyComponent));
Ключевые моменты:
component() — функция, оборачивающая обычную функцию в
полноценный веб-компонент.html — шаблонная функция, аналог JSX, создающая
виртуальное представление DOM.Haunted поддерживает концепцию Hooks, знакомую по React. Основные Hooks включают:
useState — для локального состояния.useEffect — для побочных эффектов.useReducer — для более сложного управления
состоянием.useRef — для хранения ссылок на DOM-элементы или другие
значения.Пример использования useState:
import { html, 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));
Особенность Haunted — автоматическое обновление компонента при
изменении состояния через useState.
Haunted использует синтаксис @событие=${handler} для
привязки обработчиков. Это заменяет стандартное
addEventListener, позволяя писать компактный и читаемый
код:
html`<button @click=${handleClick}>Нажми меня</button>`
handleClick — это функция, определённая внутри
компонента или импортированная извне. Такая привязка автоматически
очищается при размонтировании компонента, что предотвращает утечки
памяти.
Компоненты Haunted поддерживают реактивные свойства и атрибуты. Любое свойство, переданное компоненту, становится доступным через аргументы функции:
html`<my-component name="Иван"></my-component>`
Внутри компонента name будет доступен напрямую:
function MyComponent({ name }) {
return html`<p>Привет, ${name}!</p>`;
}
Свойства могут быть реактивными, что позволяет компоненту автоматически перерисовываться при их изменении:
const el = document.createElement('my-component');
el.name = 'Мария';
document.body.appendChild(el);
Haunted позволяет создавать сложные интерфейсы из вложенных компонентов. Любой компонент можно использовать как обычный HTML-тег внутри другого компонента:
function App() {
return html`
<div>
<my-counter></my-counter>
<my-component name="Алексей"></my-component>
</div>
`;
}
Это обеспечивает модульность и повторное использование кода.
Все компоненты Haunted по умолчанию используют Shadow DOM, что изолирует стили и структуру DOM от остальной страницы. Внутри компонента можно использовать стандартные CSS:
function StyledComponent() {
return html`
<style>
p { color: blue; font-weight: bold; }
</style>
<p>Стилизованный текст</p>
`;
}
Использование Shadow DOM повышает инкапсуляцию и предотвращает конфликт CSS с другими частями приложения.
Haunted поддерживает жизненный цикл через useEffect,
аналогично React:
import { useEffect } from 'haunted';
function Timer() {
const [time, setTime] = useState(0);
useEffect(() => {
const id = setInterval(() => setTime(t => t + 1), 1000);
return () => clearInterval(id);
}, []);
return html`<p>Время: ${time}</p>`;
}
useEffect выполняется после рендера.Haunted минимизирует количество операций с DOM, используя виртуальное представление разметки. Компоненты обновляются только при изменении состояния или свойств, что снижает нагрузку на браузер. Для больших приложений рекомендуется:
useMemo для вычислений, зависящих от
состояния.Haunted легко интегрируется с любой сторонней библиотекой JavaScript.
Любой компонент можно обернуть вокруг стороннего виджета, используя
useEffect для инициализации и очистки:
import someLibrary from 'some-library';
function WidgetWrapper({ options }) {
const ref = useRef();
useEffect(() => {
const widget = someLibrary.init(ref.current, options);
return () => widget.destroy();
}, [options]);
return html`<div ${ref}></div>`;
}
Haunted позволяет создавать собственные Hooks, что облегчает повторное использование логики:
import { useState, useEffect } from 'haunted';
function useToggle(initial = false) {
const [state, setState] = useState(initial);
const toggle = () => setState(s => !s);
return [state, toggle];
}
Такой подход упрощает управление состоянием и делает компоненты более читаемыми.
Haunted сочетает лёгкость нативных веб-компонентов с мощью реактивного подхода, обеспечивая высокую модульность, производительность и удобство разработки современных интерфейсов. Она подходит для проектов любой сложности, от небольших виджетов до крупных приложений с компонентной архитектурой.