Haunted — это легковесная библиотека для создания веб-компонентов на основе функционального подхода в JavaScript. Она объединяет концепции web components с реактивной моделью, похожей на React Hooks, обеспечивая высокую производительность и гибкость. Рассмотрим ключевые аспекты оптимизации производительности и использования контекста.
Haunted использует систему реактивных хуков, главным
образом useState и useEffect, чтобы управлять
состоянием компонентов. Важной особенностью является локальный
ререндеринг, когда изменяется состояние: Haunted обновляет
только ту часть 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 не создаёт виртуальный DOM. Вместо этого она использует template literals и lit-html-подобный рендеринг, что уменьшает накладные расходы на diffing и повышает производительность при больших приложениях.
Haunted поддерживает контекст, который позволяет
передавать данные через иерархию компонентов без необходимости
передавать их явно через props. Контекст создаётся функцией
createContext и используется через useContext
и provideContext.
Создание контекста:
import { createContext, provideContext, useContext, component, html } from 'haunted';
const ThemeContext = createContext('light');
function ThemeProvider({ theme, children }) {
provideContext(ThemeContext, theme);
return html`<slot></slot>`;
}
function ThemedButton() {
const theme = useContext(ThemeContext);
return html`<button class=${theme}>Кнопка с темой ${theme}</button>`;
}
customElements.define('theme-provider', component(ThemeProvider));
customElements.define('themed-button', component(ThemedButton));
Особенности производительности при работе с контекстом:
useContext, будут обновлены
при изменении значения.Haunted предоставляет несколько стратегий для повышения производительности:
Мемоизация функций и значений Использование
useMemo и useCallback помогает предотвратить
ненужные пересоздания функций и вычислений при каждом ререндере.
import { useMemo, html, component } from 'haunted';
function ExpensiveComponent({ items }) {
const sortedItems = useMemo(() => items.sort(), [items]);
return html`<ul>${sortedItems.map(i => html`<li>${i}</li>`)}</ul>`;
}Фрагментация DOM Haunted рендерит только изменённые узлы, что позволяет использовать вставку и удаление элементов без полной перерисовки родительского контейнера.
Отложенный ререндеринг useEffect и
useLayoutEffect позволяют выполнять операции после рендера
и предотвращают блокировку основного потока, что критично при работе с
тяжёлыми вычислениями или асинхронными запросами.
Haunted предоставляет хуки для управления жизненным циклом компонента:
useEffect — выполняется после каждого рендера, можно
задать зависимости для оптимизации.useLayoutEffect — выполняется синхронно после изменения
DOM, полезно для вычислений размеров и анимаций.useReducer — для сложного состояния, которое зависит от
предыдущего состояния, снижает количество лишних обновлений.Пример использования useEffect для асинхронного
запроса:
import { html, component, useState, useEffect } from 'haunted';
function DataFetcher({ url }) {
const [data, setData] = useState(null);
useEffect(() => {
let canceled = false;
fetch(url)
.then(res => res.json())
.then(json => { if (!canceled) setData(json); });
return () => { canceled = true; };
}, [url]);
return html`<pre>${JSON.stringify(data, null, 2)}</pre>`;
}
customElements.define('data-fetcher', component(DataFetcher));
Важный момент: возврат функции из
useEffect позволяет корректно очищать ресурсы и
предотвращает утечки памяти.
slot для передачи структурного контента,
что снижает количество пересоздаваемых элементов.Haunted сочетает функциональный подход и высокую производительность за счёт реактивных хуков и минимальной работы с DOM. Контекст позволяет управлять состоянием приложений с большим числом компонентов без потери скорости, а правильное использование мемоизации и эффектов гарантирует оптимальный рендеринг.