Цель этой серии блогов — углубиться в библиотеку Lit и получить всестороннее представление о ее уникальных функциях и о том, чем она отличается от других библиотек и фреймворков на рынке.

Эта серия разделена на три части, посвященные таким темам, как
1. Как работает lit-html?
2. Как Lit Element выполняет пакетное обновление DOM?
3. Сравнение и бенчмаркинг Lit с другими фреймворками и библиотеками, а также его возможные варианты использования.

В этом конкретном блоге мы сосредоточимся на изучении lit-html и его внутренней работы. Но прежде чем углубляться в lit-html, давайте сначала рассмотрим саму библиотеку Lit.

Что такое Освещение?

Lit — это легкая библиотека веб-компонентов, занимающая около 5 КБ.

Он специально разработан для эффективной и быстрой разработки компонентов пользовательского интерфейса с использованием спецификаций веб-компонентов и еще больше повышает производительность за счет внедрения пакетных обновлений в DOM.

Фактически, согласно общедоступному тесту, проведенному https://krausest.github.io/js-framework-benchmark/index.html, Lit Element продемонстрировал более высокую производительность по сравнению с React.

Чтобы узнать больше о Lit Element, вы можете посетить их официальный сайт по адресу https://lit.dev/. Тем не менее, в этой серии статей основное внимание уделяется пониманию того, как работает Lit Element и как он реализуется.

Lit Element построен на основе lit-html, библиотеки шаблонов, используемой для создания шаблонов и логики пакетного обновления DOM. Lit Element расширяет lit-html, предоставляя дополнительные функции для пакетных обновлений.

Создание шаблона lit-html:

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

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

Создадим шаблон с помощью библиотеки lit-html:

В этом примере мы импортируем две функции из библиотеки lit-html:
1.html, которая является функцией тега.
2.render, которая используется для отображения шаблона в DOM.

Затем мы определяем функцию с именем myTemplate, которая принимает аргумент name.

Шаблон определяется с помощью функции тега html, заключенной в обратные кавычки (``), и содержит фрагмент HTML <div>Hello, ${name}</div>.

${name} — это заполнитель, который можно динамически заменить значением во время выполнения на основе на аргумент, переданный функции myTemplate.

Функция тега html возвращает объект TemplateResult, представляющий шаблон, который можно отобразить в DOM.

В следующих разделах мы рассмотрим функцию тега JavaScript и то, как функция тега html реализована в библиотеке lit-html.

В последней строке кода мы вызываем метод render, который отображает шаблон.
Метод render принимает два аргумента:
а) TemplateResult объект, представляющий шаблон для визуализации.
б) Ссылка на элемент DOM, в котором будет отображаться шаблон.

Функция тега в JavaScript:

Примечание. Если вы уже знакомы с функциями тегов, этот раздел можно пропустить.

Функция тега в JavaScript — это особый тип функции, который можно использовать для обработки литералов шаблонов, представляющих собой строки, заключенные в обратные кавычки (``).

Функция тега вызывается непосредственно перед вычислением литерала шаблона и получает литерал шаблона и его интерполированные значения в качестве отдельных аргументов.

Например, рассмотрим следующий код:

var name = "Whatfix";
function sayHello(literalString, ...values) {
    console.log(literalString); //Output: ['Hello, ', '', raw: Array(2)]
    console.log(values); //Output: ['Whatfix']
}
sayHello`Hello, ${name}`;

В этом примере sayHello — это функция тега, которая принимает теговый литерал Hello, ${name} в качестве аргумента.
Функция тега вызывается непосредственно перед вычислением тегированного литерала. Затем он разбивает помеченный литерал на две части:

а. Массив статических частей шаблонного литерала: literalString.
В нашем примере значение параметра literalString равно ['Hello, ', '', raw: Array(2)]

б. Один или несколько аргументов, соответствующих количеству выражений в помеченном литерале: values. В нашем примере мы используем оператор спреда (...), чтобы представить его в виде массива. Его значение — ['Whatfix'], которое содержит значения выражений, используемых в литерале шаблона.

Глубокое погружение в метод html:

Вот реализация функции тега html из репозитория lit-htmlhttps://github.com/lit/lit. (Я сделал некоторые улучшения в коде, удалив ненужные части, чтобы сделать его более понятным).

const html =
  <T extends ResultType>(type: T) =>
  (strings: TemplateStringsArray, ...values: unknown[]): TemplateResult<T> => {
    return {
      ['_$litType$']: type,
      strings,
      values,
    };
  };

Подобно другим функциям тегов, функция тега html также разбивает помеченный литерал на две части и принимает их в качестве аргументов.

Затем он формирует объект, известный как TemplateResult, с тремя параметрами и возвращает его.

Три параметра TemplateResult включают _$litType$, строки и значения[].

а. Параметр _$litType$ содержит тип.
б. Параметр strings содержит массив статических частей литералов.
в. Параметр values[] содержит значения динамических частей литерала.

В нашем предыдущем примере (Шаблон — A) myTemplate("whatfix”)method вернет:

{
  _$litType$: 1,
  strings: ["<div>Hello, ", "</div>", raw: Array(2)],
  values: ["whatfix"]
}

Этот объект упоминается как TemplateResult.

Глубокое погружение в метод рендеринга:

Метод рендеринга в lit-html отвечает за рендеринг компонента в пользовательском интерфейсе.
Он принимает три аргумента:

а. value — TemplateResult, сгенерированное функцией тега html, как обсуждалось в предыдущем разделе.

б. container — ссылка на элемент DOM, в котором будет отображаться шаблон.

в. options — в целях упрощения этот аргумент можно игнорировать, чтобы лучше понять процесс.

Мы можем визуально понять работу метода рендеринга в нашем примере, используя блок-схему.

Далее давайте обработаем наш пример компонента, Шаблон A, используя вышеупомянутую блок-схему. Поскольку мы уже создали объект TemplateResult с помощью функции тега html, как обсуждалось в предыдущем разделе, теперь мы можем приступить к процессу рендеринга.

Объект TemplateResult для нашего примера компонента, шаблона A, будет иметь следующую структуру:

Следующий шаг включает создание элемента <template> из объекта TemplateResult.
В нашем примере компонента Template A, который включает динамическую часть, представленную {name}, мы генерируем случайное девятизначное число и добавляем его в качестве узла комментария вместо {name}.
В результате элемент <template> будет выглядеть следующим образом:

Следующий шаг включает в себя клонирование элемента шаблона и обновление динамических частей либо во время первого рендеринга, либо во время последующих обновлений. Клонирование элемента шаблона происходит только при первоначальном рендеринге компонента.
Результирующая структура будет выглядеть следующим образом:

Затем, используя второй аргумент, переданный методу рендеринга, мы добавляем окончательную структуру компонента в документ.

Заключение.
В этом блоге мы исследовали внутреннюю работу lit-html. В следующей части этой серии мы углубимся в пакетные операции, выполняемые в библиотеке lit с элементами lit.