Директивы lit-html

В библиотеке Haunted директивы являются мощным инструментом для расширения возможностей шаблонов, построенных с помощью lit-html. Они позволяют управлять рендерингом, состоянием и динамическим поведением элементов без необходимости вручную обновлять DOM. Директивы — это функции, возвращаемые из lit-html и вызываемые внутри шаблонов, которые получают контейнер, значение и текущую директиву, обеспечивая гибкий контроль над рендерингом.


Основные принципы работы директив

Директива — это функция, которая возвращает объект с методом update и/или render. Эти методы вызываются при каждом обновлении шаблона. Стандартный вызов выглядит следующим образом:

import { directive, html } from 'lit-html';

const myDirective = directive((value) => (part) => {
  part.setValue(`Значение: ${value}`);
});

В этом примере директива принимает value и устанавливает его в часть DOM, связанного с шаблоном.

Ключевые моменты:

  • Директива может управлять одним или несколькими parts в шаблоне.
  • Она может хранить внутреннее состояние между вызовами.
  • Использование директив уменьшает количество обновлений DOM, повышая производительность.

Использование стандартных директив

lit-html предоставляет ряд встроенных директив, которые активно применяются в Haunted для реактивного рендеринга.

1. ifDefined

Директива ifDefined позволяет рендерить значение атрибута только если оно определено. Полезна для условного добавления атрибутов:

import { html } from 'lit-html';
import { ifDefined } from 'lit-html/directives/if-defined.js';

const template = (value) => html`
  <input type="text" value="${ifDefined(value)}">
`;

Если value равен undefined, атрибут value не добавляется.


2. repeat

Директива repeat оптимизирует рендеринг массивов и списков, предотвращая повторное создание элементов при обновлениях:

import { html } from 'lit-html';
import { repeat } from 'lit-html/directives/repeat.js';

const items = ['apple', 'banana', 'cherry'];

const template = html`
  <ul>
    ${repeat(items, (item) => item, (item, index) => html`<li>${item}</li>`)}
  </ul>
`;

Пояснение параметров:

  • Первый аргумент — массив данных.
  • Второй — ключевая функция для идентификации элементов.
  • Третий — функция рендеринга элемента.

repeat предотвращает перерисовку элементов, которые не изменились, сохраняя состояние внутри элементов.


3. guard

Директива guard позволяет ограничивать обновление шаблона только при изменении определенных данных:

import { html } from 'lit-html';
import { guard } from 'lit-html/directives/guard.js';

const template = (data) => html`
  ${guard([data], () => html`<p>${data.text}</p>`)}
`;
  • Первый аргумент — массив зависимостей.
  • Второй — функция, возвращающая шаблон.

guard предотвращает ненужные вызовы рендеринга, если зависимости не изменились.


Создание собственных директив

Для создания пользовательской директивы используется функция directive, возвращающая функцию DirectiveResult. Основная структура:

import { directive, PartType } from 'lit-html';

const myDirective = directive((value) => (part) => {
  if (part.type === PartType.PROPERTY) {
    part.setValue(value.toUpperCase());
  }
});

Этапы работы пользовательской директивы:

  1. Приём данных — директива получает входные значения.
  2. Определение типа части — текст, атрибут или свойство.
  3. Обновление DOM — метод setValue применяется к части DOM.
  4. Сохранение состояния — можно хранить данные между вызовами, используя замыкания или внутренние свойства.

Интеграция директив с Haunted

Haunted строит компоненты на основе lit-html и customElements. Директивы позволяют:

  • Управлять рендерингом внутри функциональных компонентов.
  • Создавать динамические свойства элементов.
  • Оптимизировать производительность при изменении состояний.

Пример интеграции:

import { html } from 'lit-html';
import { component, useState } from 'haunted';
import { repeat } from 'lit-html/directives/repeat.js';

function TodoList({ todos }) {
  return html`
    <ul>
      ${repeat(todos, todo => todo.id, todo => html`<li>${todo.text}</li>`)}
    </ul>
  `;
}

customElements.define('todo-list', component(TodoList));

Использование repeat внутри Haunted-компонента обеспечивает минимальные перерисовки списка при изменении элементов.


Практические советы

  • Сохранять легковесность директив: чем меньше логики в директиве, тем проще поддерживать компонент.
  • Использовать встроенные директивы там, где возможно, вместо ручного обновления DOM.
  • Избегать больших вычислений в update: директива должна обновлять только DOM, вычисления лучше делать вне шаблона.
  • Хранить состояние в замыканиях, чтобы избежать глобальных переменных.

Заключение по возможностям

Директивы в Haunted с lit-html предоставляют:

  • Тонкий контроль за рендерингом.
  • Эффективное управление массивами и списками.
  • Оптимизацию обновлений при изменении данных.
  • Возможность создания сложной реактивной логики без переписывания DOM вручную.

Использование директив — ключевой элемент для построения производительных и легко поддерживаемых веб-компонентов.