Haunted — это минималистичная библиотека для создания веб-компонентов на базе Web Components и функционального подхода, вдохновлённого React Hooks. Одним из ключевых аспектов работы с Haunted являются свойства компонентов (properties). Свойства определяют внешний интерфейс компонента, его поведение и взаимодействие с внешним миром.
В Haunted свойства компонента задаются через объект
observedAttributes или через декоратор
@property (если используется TypeScript и соответствующие
расширения). Основная цель — связать внешние атрибуты элемента с
внутренним состоянием компонента.
import { component, html } from 'haunted';
function MyComponent({ title }) {
return html`<h1>${title}</h1>`;
}
customElements.define('my-component', component(MyComponent, { observedAttributes: ['title'] }));
Здесь title — это свойство компонента, которое
автоматически отражается в DOM как атрибут и может передаваться при
использовании элемента:
<my-component title="Пример"></my-component>.
Haunted не накладывает жёстких ограничений на типы свойств, однако важно понимать различие между строковыми атрибутами HTML и типами JavaScript, которые фактически используются внутри компонента.
Строковые свойства Атрибуты HTML всегда передаются как строки. Haunted автоматически преобразует значение атрибута в строку, если не используется кастомное преобразование. Это удобно для текстовых данных:
function TextComponent({ text }) {
return html`<p>${text}</p>`;
}
customElements.define('text-component', component(TextComponent, { observedAttributes: ['text'] }));
Здесь
<text-component text="Привет"></text-component>
передаст значение "Привет" в свойство
text.
Булевы свойства Булевы значения в HTML задаются
особым образом: наличие атрибута означает true, а
отсутствие — false. В Haunted это можно обработать с
помощью функции-преобразователя:
function Toggle({ active }) {
return html`<div class="${active ? 'on' : 'off'}"></div>`;
}
customElements.define('toggle-switch', component(Toggle, {
observedAttributes: {
active: {
converter: (value) => value !== null
}
}
}));
Теперь
<toggle-switch active></toggle-switch> создаст
включённый элемент, а
<toggle-switch></toggle-switch> —
выключенный.
Числовые свойства Для чисел необходимо явно
конвертировать строку из атрибута в число, иначе Haunted будет
использовать строку. Обычно используется Number() или
parseInt/parseFloat:
function Counter({ count }) {
return html`<p>Счёт: ${count}</p>`;
}
customElements.define('counter-element', component(Counter, {
observedAttributes: {
count: {
converter: (value) => Number(value)
}
}
}));
Теперь
<counter-element count="42"></counter-element>
корректно передаст число 42 в свойство
count.
Объектные и массивные свойства Так как HTML-атрибуты — строки, объекты и массивы нужно передавать через сериализацию, например, в JSON:
function List({ items }) {
return html`<ul>${items.map(item => html`<li>${item}</li>`)}</ul>`;
}
customElements.define('list-component', component(List, {
observedAttributes: {
items: {
converter: (value) => JSON.parse(value)
}
}
}));
Использование:
<list-component items='["яблоко","банан"]'></list-component>.
Haunted автоматически перерисовывает компонент при изменении свойств.
Любое изменение в объекте observedAttributes вызывает
повторный рендер.
const el = document.querySelector('counter-element');
el.count = 10; // автоматически обновится отображение
Важно: если свойство является объектом или массивом, Haunted отслеживает только изменение ссылки, а не внутренние мутации. Для перерисовки нужно присвоить новое значение:
el.items = [...el.items, 'груша'];
Haunted позволяет разделять внутренние свойства и атрибуты HTML. Атрибут может существовать, но не обязательно отображать сложные внутренние состояния. Рекомендуется придерживаться следующих правил:
Пример смешанного подхода:
function UserCard({ name, age, onClick }) {
return html`<div @click=${onClick}>${name}, ${age} лет</div>`;
}
customElements.define('user-card', component(UserCard, {
observedAttributes: ['name', 'age']
}));
const card = document.createElement('user-card');
card.name = 'Иван';
card.age = 30;
card.onCl ick = () => alert('Клик!');
document.body.appendChild(card);
Haunted поддерживает установку значений по умолчанию через деструктуризацию аргументов функции компонента:
function Badge({ label = 'Новый', color = 'blue' }) {
return html`<span style="color:${color}">${label}</span>`;
}
Если атрибут не передан, компонент использует дефолтные значения. Это особенно полезно для создания гибких, переиспользуемых компонентов.
Haunted позволяет создавать компоненты с гибким интерфейсом, где свойства и атрибуты управляют состоянием и визуализацией, обеспечивая предсказуемое поведение и простую интеграцию с другими веб-стандартами.