Синтаксис шаблонов lit-html

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

Шаблоны в lit-html создаются с помощью тега html, который обрабатывает строки шаблонов, содержащие интерполяцию.

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

const name = 'Мир';
const template = html`<p>Привет, ${name}!</p>`;
render(template, document.body);

В данном примере ${name}выражение, вставляемое в шаблон. Lit автоматически отслеживает изменения значений и обновляет DOM без полного рендера всего дерева.


Интерполяция и выражения

Любое выражение JavaScript может быть использовано внутри ${}:

const items = ['Яблоко', 'Банан', 'Вишня'];
const listTemplate = html`
  <ul>
    ${items.map(item => html`<li>${item}</li>`)}
  </ul>
`;

Особенности:

  • Поддерживаются вложенные шаблоны (html`` внутри${}`).
  • Любое вычисление или вызов функции автоматически отражается в рендере.
  • Lit не экранирует значения, если они сами являются шаблонами (html).

Атрибуты и свойства

Для связывания значений с атрибутами элементов используется синтаксис .prop и ?bool:

const isDisabled = true;
const buttonTemplate = html`<button ?disabled=${isDisabled}>Нажми</button>`;
  • ?disabled=${isDisabled} — связывает булево значение с атрибутом.
  • .value=${value} — связывает свойство элемента напрямую, что важно для <input> и <textarea>.
const inputValue = 'Тест';
const inputTemplate = html`<input .value=${inputValue}>`;

События

Lit позволяет привязывать обработчики событий с помощью синтаксиса @event:

const handleClick = () => console.log('Клик!');
const button = html`<button @click=${handleClick}>Нажми меня</button>`;

Особенности:

  • События автоматически делегируются.
  • Используются реальные DOM-обработчики, что обеспечивает высокую производительность.
  • Обработчики могут быть анонимными функциями или ссылками на методы класса.

Директивы

Lit предоставляет директивы — специальные функции для расширенного управления шаблоном.

Примеры:

  • repeat — рендер массивов с оптимизацией обновлений:
import { repeat } from 'lit/directives/repeat.js';

const users = [{id:1, name:'Анна'}, {id:2, name:'Борис'}];
const userList = html`
  <ul>
    ${repeat(users, user => user.id, user => html`<li>${user.name}</li>`)}
  </ul>
`;
  • ifDefined — вставка атрибута только если значение определено:
import { ifDefined } from 'lit/directives/if-defined.js';

const imgSrc = undefined;
const imageTemplate = html`<img src=${ifDefined(imgSrc)} alt="Пример">`;
  • guard — предотвращение ненужного рендера части шаблона:
import { guard } from 'lit/directives/guard.js';

const template = guard([data], () => html`<p>${data.value}</p>`);

Безопасность и экранирование

Lit-html автоматически экранирует строки, чтобы предотвратить XSS:

const userInput = '<script>alert("XSS")</script>';
const safeTemplate = html`<p>${userInput}</p>`; // скрипт не выполнится

Если необходимо вставить неэкранированный HTML, используется директива unsafeHTML из lit/directives/unsafe-html.js:

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

const rawHtml = '<strong>Важное!</strong>';
const template = html`<div>${unsafeHTML(rawHtml)}</div>`;

Стилизация внутри шаблонов

Lit позволяет создавать CSS-шаблоны напрямую в компоненте с помощью css и style:

import { css, html, LitElement } from 'lit';

class MyComponent extends LitElement {
  static styles = css`
    p {
      color: blue;
      font-weight: bold;
    }
  `;

  render() {
    return html`<p>Стилизованный текст</p>`;
  }
}

customElements.define('my-component', MyComponent);

Особенности:

  • Стили изолированы для конкретного веб-компонента.
  • Можно использовать переменные CSS и вложенные селекторы.
  • Поддерживаются директивы и динамические свойства через style="${...}".

Итоговое понимание

Синтаксис шаблонов Lit строится вокруг трёх ключевых элементов:

  1. Шаблонные литералы (html) для декларативного описания DOM.
  2. Интерполяция ${} для динамического контента.
  3. Директивы для расширенной функциональности и оптимизации обновлений.

Такой подход обеспечивает высокую производительность, реактивность и удобство поддержки больших веб-приложений, позволяя создавать динамические интерфейсы с минимальным количеством кода.