Haunted — это современная библиотека для создания веб-компонентов на основе Web Components с использованием реактивного подхода, аналогичного React. Основная сила Haunted заключается в том, что она позволяет связывать свойства компонента с его рендером, обеспечивая автоматическое обновление интерфейса при изменении данных.
В Haunted ключевым элементом является свойство
компонента, объявляемое с помощью функции useState
или useReducer. Эти свойства являются реактивными, то есть
при их изменении автоматически инициируется повторный
рендер компонента.
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));
Ключевые моменты:
useState возвращает массив
[значение, функцияОбновления].setCount инициирует ререндер
компонента.html, которая
отслеживает изменения и обновляет DOM.Помимо локального состояния через useState, Haunted
поддерживает реактивные свойства, передаваемые через
атрибуты. Для этого используется
observedAttributes и привязка значений через конструктор
компонента или декораторы.
import { component, html, useState } from 'haunted';
function Greeting({ name }) {
const [greet, setGreet] = useState(`Привет, ${name}!`);
return html`<p>${greet}</p>`;
}
Greeting.observedAttributes = ['name'];
customElements.define('my-greeting', component(Greeting));
name компонент повторно
рендерится с новым значением.observedAttributes.Haunted позволяет создавать вычисляемые значения,
которые зависят от одного или нескольких состояний. Такие значения можно
реализовать через useEffect или простую функцию внутри
компонента.
import { html, component, useState, useEffect } from 'haunted';
function DoubleCounter() {
const [count, setCount] = useState(0);
const [double, setDouble] = useState(count * 2);
useEffect(() => {
setDouble(count * 2);
}, [count]);
return html`
<p>Счетчик: ${count}</p>
<p>Удвоенное значение: ${double}</p>
<button @click=${() => setCount(count + 1)}>Увеличить</button>
`;
}
customElements.define('double-counter', component(DoubleCounter));
Особенности:
useEffect позволяет реагировать на изменения
зависимостей [count].count автоматически
пересчитает double.По умолчанию Haunted не отслеживает глубокие изменения объектов или массивов. Если требуется реактивность для вложенных данных, необходимо создавать новые объекты при обновлении состояния.
const [user, setUser] = useState({ name: 'Иван', age: 30 });
// Правильное обновление
setUser({ ...user, age: user.age + 1 });
// Неправильное обновление (не вызовет ререндер)
user.age += 1;
Haunted поддерживает несколько состояний в одном компоненте, что позволяет строить сложные реактивные интерфейсы без дополнительных библиотек.
function Profile() {
const [name, setName] = useState('Алексей');
const [age, setAge] = useState(25);
return html`
<p>Имя: ${name}</p>
<p>Возраст: ${age}</p>
<button @click=${() => setAge(age + 1)}>Добавить год</button>
<button @click=${() => setName('Мария')}>Изменить имя</button>
`;
}
customElements.define('user-profile', component(Profile));
useState управляет отдельной реактивной
переменной.useEffect для побочных
эффектов, не связанных напрямую с DOM.observedAttributes, если предполагается их динамическое
изменение.Haunted реализует реактивность через простую, но мощную комбинацию хуков состояния, эффектов и наблюдаемых атрибутов, позволяя создавать веб-компоненты, которые интерактивно реагируют на изменения данных без сложных внешних библиотек.