Haunted — это библиотека для создания веб-компонентов на основе хуков в стиле React. Одной из ключевых особенностей является система встроенных директив, позволяющая управлять поведением шаблонов в процессе рендеринга. Директивы — это функции, которые возвращают специальные значения для шаблона, изменяя стандартное поведение Lit или html-шаблонов.
Директива в Haunted применяется внутри шаблонных литералов. Вместо обычного выражения, которое рендерится как текст, директива получает доступ к контексту рендеринга и может изменять DOM более тонко. Это особенно полезно для:
Директивы в Haunted используют функцию directive из
пакета haunted/directive. Простейшая форма выглядит
так:
import { html, render } from 'haunted';
import { directive } from 'haunted/directive';
const myDirective = directive((value) => (part) => {
part.setValue(`Значение: ${value}`);
});
render(html`<div>${myDirective('Тест')}</div>`, document.body);
Здесь part — это объект, представляющий участок
DOM, который директива может изменять. Метод
setValue позволяет напрямую менять содержимое элемента без
повторного рендеринга всего шаблона.
Haunted не содержит полноценного JSX-синтаксиса, но встроенные директивы позволяют реализовать условное отображение. Например:
import { html } from 'haunted';
import { ifDefined } from 'haunted/directives/if-defined.js';
const userName = null;
html`<p>Имя: ${ifDefined(userName)}</p>`;
ifDefined предотвращает рендеринг undefined
и null как строки "undefined" или
"null". Это особенно важно при работе с динамическими
данными.
Для более сложного условного рендеринга можно использовать пользовательские директивы:
import { directive } from 'haunted/directive';
const showIf = directive((condition, template) => (part) => {
if (condition) {
part.setValue(template);
} else {
part.setValue('');
}
});
html`${showIf(true, html`<p>Отображается только если условие истинно</p>`)}`
Для рендеринга массивов данных часто используют встроенные или пользовательские директивы, которые оптимизируют повторное обновление без полной перерисовки:
import { repeat } from 'haunted/directives/repeat.js';
const items = ['яблоко', 'банан', 'вишня'];
html`
<ul>
${repeat(items, (item) => item, (item, index) => html`<li>${item}</li>`)}
</ul>
`;
Параметры repeat:
Такой подход минимизирует манипуляции с DOM и повышает производительность.
Директивы могут управлять атрибутами элементов, позволяя динамически изменять свойства:
import { ifDefined } from 'haunted/directives/if-defined.js';
const href = null;
html`<a href="${ifDefined(href)}">Ссылка</a>`;
Использование ifDefined гарантирует, что атрибут
href будет полностью отсутствовать, если значение не
определено, а не будет отображаться как "null".
Создание кастомной директивы позволяет внедрять собственную логику обновления DOM:
import { directive } from 'haunted/directive';
const highlight = directive((color) => (part) => {
part.startNode.parentNode.style.backgroundColor = color;
});
html`<p>${highlight('yellow')}Выделенный текст</p>`;
Жизненный цикл кастомной директивы ограничен обновлениями
соответствующего part. Это означает:
В Haunted можно комбинировать директивы, создавая цепочки обработки шаблонов. Например, условное рендеринг + повторение:
import { repeat } from 'haunted/directives/repeat.js';
import { directive } from 'haunted/directive';
const showList = directive((condition, items) => (part) => {
if (!condition) {
part.setValue('');
return;
}
part.setValue(html`
<ul>
${repeat(items, (item) => item.id, (item) => html`<li>${item.name}</li>`)}
</ul>
`);
});
html`${showList(true, [{ id: 1, name: 'Первый' }, { id: 2, name: 'Второй' }])}`;
Такой подход делает шаблоны компактными, при этом сохраняя высокую гибкость и производительность.
repeat или кастомная директива с ключами) для минимизации
перерисовки.ifDefined, чтобы избегать
некорректного рендеринга null и
undefined.part.Haunted встроенные директивы позволяют создавать динамичные, оптимизированные и легко управляемые шаблоны. Они объединяют гибкость функциональных компонентов с высокой производительностью DOM-операций, делая работу с веб-компонентами более предсказуемой и управляемой.