Haunted — это библиотека для создания веб-компонентов на основе
веб-стандартов, использующая функциональный подход, схожий с React
Hooks. Основной единицей является компонент, который создается функцией
и возвращает шаблон на lit-html. Работа со списками и
циклами в Haunted требует понимания реактивного обновления состояния и
правильного использования map и repeat.
mapМетод map является ключевым инструментом для рендеринга
списков в Haunted. Каждый элемент массива преобразуется в шаблон
lit-html:
import { html, component, useState } from 'haunted';
function TodoList({ todos }) {
return html`
<ul>
${todos.map(todo => html`<li>${todo}</li>`)}
</ul>
`;
}
customElements.define('todo-list', component(TodoList));
Особенности использования map в
Haunted:
useState, чтобы
инициировать повторный рендер.Для динамических списков важно правильно управлять состоянием с
помощью useState или пользовательских хуков:
function DynamicList() {
const [items, setItems] = useState(['Элемент 1', 'Элемент 2']);
const addItem = () => setItems([...items, `Элемент ${items.length + 1}`]);
return html`
<ul>
${items.map(item => html`<li>${item}</li>`)}
</ul>
<button @click=${addItem}>Добавить элемент</button>
`;
}
customElements.define('dynamic-list', component(DynamicList));
Ключевые моменты:
items содержит массив для рендеринга.addItem создает новый массив, чтобы сохранить
иммутабельность.for внутри шаблоновВ Haunted нельзя напрямую использовать стандартный for
для генерации шаблонов, так как lit-html ожидает массив
шаблонов. Но можно создавать массив заранее:
function NumberList({ count }) {
const numbers = [];
for (let i = 1; i <= count; i++) {
numbers.push(html`<li>${i}</li>`);
}
return html`<ul>${numbers}</ul>`;
}
customElements.define('number-list', component(NumberList));
Особенности такого подхода:
Для массивов объектов часто требуется рендерить элементы с множеством свойств:
function UsersList({ users }) {
return html`
<ul>
${users.map(user => html`
<li>
<strong>${user.name}</strong> — ${user.email}
</li>
`)}
</ul>
`;
}
customElements.define('users-list', component(UsersList));
Особенности:
map для
упрощения кода.repeatДля больших массивов рекомендуется использовать директиву
repeat из lit-html/directives/repeat.js,
которая снижает количество повторных рендеров:
import { repeat } from 'lit-html/directives/repeat.js';
function LargeList({ items }) {
return html`
<ul>
${repeat(items, item => item.id, item => html`<li>${item.name}</li>`)}
</ul>
`;
}
customElements.define('large-list', component(LargeList));
Пояснения:
Haunted позволяет создавать интерактивные списки, где элементы добавляются или удаляются:
function EditableList() {
const [items, setItems] = useState(['A', 'B', 'C']);
const removeItem = index => setItems(items.filter((_, i) => i !== index));
return html`
<ul>
${items.map((item, index) => html`
<li>
${item} <button @click=${() => removeItem(index)}>Удалить</button>
</li>
`)}
</ul>
`;
}
customElements.define('editable-list', component(EditableList));
Важно:
Списки часто требуют условного рендеринга элементов:
function FilteredList({ items, showEven }) {
return html`
<ul>
${items
.filter(item => !showEven || item % 2 === 0)
.map(item => html`<li>${item}</li>`)}
</ul>
`;
}
customElements.define('filtered-list', component(FilteredList));
Особенности:
map.С помощью перечисленных подходов Haunted позволяет эффективно
работать с массивами, динамическими списками и условиями, обеспечивая
реактивность и минимальное количество лишних перерисовок. Комбинация
map, repeat и хуков состояния формирует основу
управления любыми коллекциями данных в функциональных компонентах.