Haunted — это легковесная библиотека для создания веб-компонентов на базе Web Components и Hooks, вдохновлённая подходом React. Одним из ключевых аспектов при работе с Haunted является использование утилитарных типов, которые упрощают управление состоянием, обработку свойств и оптимизацию рендеринга. Эти типы не являются встроенными в язык JavaScript напрямую, но формируют архитектурную основу при построении компонентов.
html и шаблонные
литералыВ Haunted рендеринг компонента строится через функцию
html, которая возвращает шаблон с использованием
template literals. Она является фундаментальным
утилитарным инструментом, обеспечивающим:
Пример использования:
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));
Ключевой момент: ${...} позволяет внедрять динамические
значения, сохраняя реактивность без прямого вмешательства в DOM.
component как
утилитарный типcomponent в Haunted превращает обычную функцию в
полноценный Web Component, автоматически управляя
жизненным циклом. Это утилитарный тип, поскольку скрывает сложную логику
регистрации и связывания с Shadow DOM.
Особенности:
useState, useEffect, useRef)
внутри функциональных компонентов.Пример:
import { component, html, useEffect } from 'haunted';
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => setSeconds(s => s + 1), 1000);
return () => clearInterval(interval);
}, []);
return html`<p>Прошло секунд: ${seconds}</p>`;
}
customElements.define('my-timer', component(Timer));
useState и
реактивные значенияuseState является утилитарным типом для
управления локальным состоянием компонента. Он
возвращает массив [state, setState]:
state — текущее значение.setState — функция для обновления значения,
автоматически вызывающая ререндер компонента.Важно помнить:
setState с тем же значением компонент не
перерендеривается.Пример с объектом:
const [user, setUser] = useState({ name: 'Alice', age: 25 });
setUser({ ...user, age: user.age + 1 });
useEffect для
побочных эффектовuseEffect позволяет выполнять код после рендера или при
изменении зависимостей. Утилитарность выражается в управлении
побочными эффектами без необходимости писать
собственные обработчики жизненного цикла.
Сигнатура: useEffect(callback, dependencies)
callback — функция, которая выполняется после
рендера.dependencies — массив зависимостей, при изменении
которых эффект перезапускается. Пустой массив означает один вызов при
монтировании.Пример:
useEffect(() => {
console.log('Компонент смонтирован');
return () => console.log('Компонент размонтирован');
}, []);
useRef для управления
DOMuseRef предоставляет ссылку на DOM-элемент или любое
изменяемое значение, сохраняя его между рендерами:
const inputRef = useRef();
function focusInput() {
inputRef.current.focus();
}
return html`
<input type="text" ${ref(inputRef)} />
<button @click=${focusInput}>Фокус на input</button>
`;
Особенности:
useReducer для
сложного состоянияuseReducer — утилитарный тип для управления сложными
состояниями, заменяющий цепочку вызовов useState:
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
return state;
}
}
const [state, dispatch] = useReducer(reducer, { count: 0 });
return html`
<p>Счёт: ${state.count}</p>
<button @click=${() => dispatch({ type: 'increment' })}>+</button>
<button @click=${() => dispatch({ type: 'decrement' })}>-</button>
`;
Преимущество useReducer — ясная структура
управления состоянием и предсказуемость поведения при сложных
изменениях.
ref и управление
атрибутамиHaunted предоставляет утилиту ref для привязки
DOM-элементов к переменным:
useRef.import { ref, useRef } from 'haunted';
const myDivRef = useRef();
return html`
<div ${ref(myDivRef)}>Контент</div>
`;
Одним из сильных преимуществ Haunted является сочетание
утилитарных типов. Например, использование
useState с html и component
позволяет создавать реактивные компоненты с минимальным количеством
кода:
function Toggle() {
const [on, setOn] = useState(false);
return html`
<button @click=${() => setOn(!on)}>
${on ? 'Включено' : 'Выключено'}
</button>
`;
}
customElements.define('my-toggle', component(Toggle));
Эта комбинация заменяет необходимость ручного управления DOM, событий и состояния, делая код декларативным и легким для поддержки.
html — шаблонная функция для безопасного и реактивного
рендеринга.component — обёртка для создания Web Components с
поддержкой Hooks.useState, useReducer — управление
локальным и сложным состоянием.useEffect — управление побочными эффектами.useRef и ref — работа с DOM-элементами без
ререндеров.Совместное использование этих утилитарных типов формирует структурированный, реактивный и лёгкий для поддержки код, позволяя создавать современные веб-компоненты без громоздких классов и ручного управления жизненным циклом.