Lit предоставляет мощный механизм для работы с шаблонами через
директивы, которые позволяют динамически изменять поведение
рендеринга без необходимости модифицировать сам компонент. Директивы
представляют собой функции или классы, управляющие частью DOM, и
применяются внутри шаблонов, создаваемых с помощью html или
svg. Создание собственных директив расширяет возможности
фреймворка и позволяет реализовать сложные сценарии обновления DOM.
Директива в Lit — это объект, который контролирует рендеринг конкретного узла шаблона. В момент первого рендера директива получает ссылку на узел DOM и контейнер, в который этот узел вставлен. При последующих обновлениях директива вызывается с новыми значениями, что позволяет:
Ключевой момент: директивы работают на уровне слабой связки с компонентом, а не изменяют его напрямую. Это обеспечивает высокую производительность и предсказуемость обновлений.
В Lit существует два основных типа директив:
Функциональные директивы Представляют собой
функции, которые возвращают класс-наследник Directive. Их
преимущество — простота и минимальный объем кода. Они идеально подходят
для одноразового изменения узла.
Классовые директивы Более гибкий вариант.
Создается класс, наследующий Directive, и реализуются
методы render и update. Используются, когда
требуется хранить внутреннее состояние между вызовами.
Простейший пример — директива, добавляющая CSS-класс к элементу, если условие истинно:
import { directive, NodePart } from 'lit/directive.js';
const conditionalClass = directive((className, condition) => (part) => {
if (!(part instanceof NodePart)) return;
if (condition) {
part.startNode.parentElement.classList.add(className);
} else {
part.startNode.parentElement.classList.remove(className);
}
});
Использование внутри шаблона:
html`<div ${conditionalClass('active', isActive)}>Контент</div>`
Преимущество функционального подхода — лаконичность. Недостаток — невозможность легко хранить сложное состояние между обновлениями.
Для более сложных сценариев используется классовая директива. Она
наследует Directive и реализует метод update,
который вызывается при каждом обновлении:
import { directive, Directive, PartType } from 'lit/directive.js';
class HighlightDirective extends Directive {
constructor(partInfo) {
super(partInfo);
if (partInfo.type !== PartType.CHILD) {
throw new Error('HighlightDirective можно использовать только с текстовыми узлами');
}
}
render(text) {
return `<span style="background-color: yellow">${text}</span>`;
}
update(part, [text]) {
part.setValue(this.render(text));
return part.commit();
}
}
export const highlight = directive(HighlightDirective);
Применение в шаблоне:
html`<p>${highlight('Важный текст')}</p>`
Особенности классовых директив:
this.someState).Директивы принимают параметры, передаваемые как массив аргументов. При обновлении шаблона Lit автоматически вызывает директиву с новыми значениями. Чтобы избежать лишних рендеров, внутри директивы можно хранить предыдущие значения и сравнивать их с текущими:
class ToggleDirective extends Directive {
previousValue;
render(value) {
return value ? 'Включено' : 'Выключено';
}
update(part, [value]) {
if (value === this.previousValue) return part;
this.previousValue = value;
return part.setValue(this.render(value));
}
}
export const toggle = directive(ToggleDirective);
Такой подход позволяет реализовать эффективное управление DOM без перерисовки всего узла.
Директивы часто применяются для:
Пример условного рендеринга:
import { ifDefined } from 'lit/directives/if-defined.js';
html`<img src="${ifDefined(imageUrl)}" alt="Картинка">`
Здесь ifDefined — встроенная директива, которая удаляет
атрибут, если значение undefined, что позволяет избежать
появления пустых атрибутов в DOM.
partInfo.type, чтобы
избежать ошибок при применении к неподходящим частям шаблона.Lit предоставляет готовые базовые директивы, такие как
repeat, asyncAppend, asyncReplace
и ifDefined. Создание пользовательских директив позволяет
сочетать эти встроенные механизмы с кастомной логикой, создавая
высокоэффективные, реактивные интерфейсы без потери
производительности.
Понимание принципов работы директив — ключ к построению масштабируемых и поддерживаемых приложений на Lit, где каждая часть шаблона управляется максимально эффективно и предсказуемо.