В Lit управление динамическим контентом и повторяющимися элементами
осуществляется с помощью встроенных возможностей шаблонов и директив. В
отличие от традиционных подходов в чистом JavaScript, здесь нет
необходимости вручную создавать элементы DOM для каждой записи — шаблоны
автоматически обновляются при изменении данных. Основным инструментом
для циклического рендеринга является директива repeat из
пакета lit/directives/repeat.js.
repeatДиректива repeat предназначена для оптимизированного
рендеринга списков. Она принимает три аргумента:
Пример:
import { html, LitElement } from 'lit';
import { repeat } from 'lit/directives/repeat.js';
class ItemList extends LitElement {
static properties = {
items: { type: Array }
};
constructor() {
super();
this.items = [
{ id: 1, name: 'Элемент 1' },
{ id: 2, name: 'Элемент 2' },
{ id: 3, name: 'Элемент 3' }
];
}
render() {
return html`
<ul>
${repeat(
this.items,
item => item.id,
item => html`<li>${item.name}</li>`
)}
</ul>
`;
}
}
customElements.define('item-list', ItemList);
В этом примере repeat гарантирует, что при изменении
массива items обновятся только те элементы, которые реально
изменились, что повышает производительность по сравнению с обычной
генерацией массива через map.
mapДля простых случаев можно использовать метод массива
map:
render() {
return html`
<ul>
${this.items.map(item => html`<li>${item.name}</li>`)}
</ul>
`;
}
Однако при изменении массива Lit пересоздаст все элементы списка, даже если изменился только один, что может быть менее эффективно для больших данных.
Часто требуется отображать только часть массива. В Lit это реализуется с помощью комбинации фильтров массива и шаблонов:
render() {
return html`
<ul>
${this.items
.filter(item => item.id % 2 === 0)
.map(item => html`<li>${item.name}</li>`)}
</ul>
`;
}
Фильтруя данные до передачи в шаблон, можно создавать сложные динамические списки с минимальной нагрузкой на DOM.
Вложенные циклы позволяют рендерить структуры типа таблиц или списков списков:
render() {
const categories = [
{ name: 'Фрукты', items: ['Яблоко', 'Банан'] },
{ name: 'Овощи', items: ['Морковь', 'Помидор'] }
];
return html`
${categories.map(category => html`
<h3>${category.name}</h3>
<ul>
${category.items.map(item => html`<li>${item}</li>`)}
</ul>
`)}
`;
}
Каждый уровень шаблона обрабатывается отдельно, сохраняя реактивность и минимальные изменения DOM при обновлении данных.
repeat:
уникальные идентификаторы позволяют Lit точно определять, какие элементы
были добавлены, удалены или изменены.map могут создавать лишние вызовы рендера.Lit автоматически отслеживает изменения свойств, объявленных в
static properties. При обновлении массива через присвоение
нового значения или метод splice шаблон будет повторно
вычислен. Важно создавать новые массивы при изменении данных, чтобы Lit
корректно детектировал изменения:
this.items = [...this.items, { id: 4, name: 'Элемент 4' }];
Использование методов, изменяющих массив на месте (push,
pop) без создания нового массива может не вызывать
перерендер.
При итерации по данным можно динамически задавать атрибуты и события:
render() {
return html`
<ul>
${this.items.map(item => html`
<li @click=${() => this.handleClick(item.id)}>
${item.name}
</li>
`)}
</ul>
`;
}
handleClick(id) {
console.log('Выбран элемент:', id);
}
Каждый элемент получает индивидуальный обработчик, что упрощает управление событиями для больших списков.
repeat и
map| Параметр | repeat |
map |
|---|---|---|
| Производительность | Высокая при изменениях | Средняя, перерисовка всех элементов |
| Поддержка ключей | Да, уникальный идентификатор | Нет |
| Простота кода | Немного сложнее | Очень просто |
| Применение | Большие списки, часто обновляемые | Небольшие статические списки |
Использование циклов и итераций в Lit сочетает удобство
декларативного подхода с высокой производительностью и реактивностью.
Правильное применение repeat, фильтров, вложенных циклов и
динамических обработчиков событий позволяет строить сложные интерфейсы с
минимальными затратами ресурсов.