Haunted — это современная библиотека для создания веб-компонентов на
базе стандартов Custom Elements, использующая функциональный подход,
схожий с React Hooks. Одним из ключевых инструментов оптимизации
производительности в Haunted является useMemo, который
позволяет кэшировать вычисления и предотвращать лишние перерасчёты при
каждом рендере компонента.
useMemouseMemo — это hook, предназначенный для мемоизации
дорогих вычислений, зависящих от конкретных значений.
Его сигнатура в Haunted выглядит следующим образом:
const memoizedValue = useMemo(fn, deps);
fn — функция, результат выполнения которой необходимо
мемоизировать.deps — массив зависимостей, при изменении которых
fn будет выполнена заново.Принцип работы аналогичен React: Haunted отслеживает зависимости и пересчитывает значение только тогда, когда хотя бы одна из них изменилась.
Рассмотрим компонент, который генерирует список чисел с дорогостоящей обработкой:
import { html, useMemo } from 'haunted';
function NumberList({ numbers }) {
const processedNumbers = useMemo(() => {
console.log('Вычисление списка');
return numbers.map(n => n * 2).filter(n => n % 3 === 0);
}, [numbers]);
return html`
<ul>
${processedNumbers.map(n => html`<li>${n}</li>`)}
</ul>
`;
}
Разбор примера:
useMemo получает функцию, которая выполняет обработку
массива numbers.numbers.numbers,
вычисление не происходит, экономя ресурсы.useMemo
в Haunted от ReactМалый размер библиотеки. Haunted не включает виртуальный DOM, поэтому мемоизация выполняется без лишней нагрузки на дерево компонентов.
Прямое использование в Custom Elements. Мемои́зация работает в контексте Shadow DOM и не зависит от виртуальной структуры.
Поведение при undefined или пустых
зависимостях:
const value = useMemo(() => compute(), []); // вычисление выполнится один раз
const value2 = useMemo(() => compute()); // вычисление выполнится на каждый рендер
Без массива зависимостей useMemo работает как обычное
вычисление при каждом рендере.
useMemo часто используется вместе с
useState и useEffect для предотвращения лишних
эффектов:
import { html, useMemo, useState, useEffect } from 'haunted';
function FilteredList({ items }) {
const [filter, setFilter] = useState('');
const filtered = useMemo(() => {
return items.filter(item => item.includes(filter));
}, [items, filter]);
useEffect(() => {
console.log('Фильтр обновлён');
}, [filtered]);
return html`
<input type="text" @input=${e => setFilter(e.target.value)} />
<ul>
${filtered.map(item => html`<li>${item}</li>`)}
</ul>
`;
}
Особенности:
filtered предотвращает лишние вызовы
useEffect.filter или items
происходит пересчёт только filtered, а не всего
компонента.useMemo стоит применять только для дорогих
вычислений, иначе накладные расходы на хранение кэша могут
превысить выигрыш.Комплексные объекты и массивы как зависимости В
Haunted useMemo проверяет зависимости по ссылке. Изменение
даже одного элемента в массиве или объекте приведёт к пересчёту:
const memo = useMemo(() => compute(arr), [arr]);
arr.push(5); // useMemo не сработает без создания новой ссылки: useMemo(() => compute(arr), [[...arr]])Встроенные функции и стрелочные выражения При
передаче функций в зависимости необходимо создавать стабильные ссылки
через useCallback или выносить их за пределы рендера, чтобы
мемоизация работала корректно.
useMemo в Haunted обеспечивает эффективную оптимизацию
компонентов за счёт предотвращения лишних вычислений и интегрируется с
функциональным подходом библиотеки. Его правильное использование
особенно важно при работе с большими списками, сложными вычислениями и
взаимодействиями с DOM в Shadow DOM.