Répéter l'utilitaire
L'utilitaire repeat est le moyen recommandé par Markup pour restituer des données itérables ou du contenu répétitif. Il gère des éléments tels que la mise en cache et le suivi du modèle, garantissant que les modifications de la liste ne concernent que les éléments qui en ont besoin.
html`${repeat(todos, renderTodo)}`Pourquoi utiliser la répétition ?
Les modèles Markup gèrent déjà les tableaux, mais comme toute autre valeur injectée, Markup suit l'ensemble et non ses éléments individuels.
const [todos, updateTodos] = state([])
html`${() => todos().map(renderTodo)}`.render(document.body)
updateTodos((prev) => [
...prev,
{
name: 'Go to gym',
status: 'pending',
},
])Le code ci-dessus fonctionnera très bien pour le rendu d'une liste. Le problème devient évident lorsqu'un seul élément change, est ajouté ou supprimé. En effet, la fonction sera à nouveau appelée, générant une toute nouvelle liste de contenu à restituer. Si Markup voit une nouvelle liste, il restituera tout.
La meilleure façon est de ne pas mapper dynamiquement la liste lors du rendu mais lors de la création afin que Markup ait toujours les éléments que vous souhaitez restituer afin qu'il puisse vérifier si c'est différent d'avant ou non.
const [todos, updateTodos] = state([])
html`${todos}`.render(document.body)
updateTodos((prev) => [
...prev,
renderTodo({
name: 'Go to gym',
status: 'pending',
}),
])C'est exactement ce que l'utilitaire repeat fait pour vous en prenant simplement les données et la fonction de rendu.
Numéros
L'assistant repeat accepte un certain nombre de choses parmi tant d'autres. Ce nombre représente le nombre de fois que vous souhaitez que la fonction de rendu de rappel soit appelée.
html`${repeat(3, html`<spa></span>`)}`La fonction de rappel sera appelée avec des nombres allant de 1 au numéro que vous avez fourni avec les index.
html`${repeat(3, (n, index) => html`<spa>${n} - ${index}</span>`)}`.render(
document.body
)
// <span>1 - 0</span><span>2 - 1</span><span>3 - 2</span>Itérables et littéraux d'objet
De plus, repeat peut consommer n'importe quel objet littéral ou objet itérable, ce qui inclut :
- Tableau
- Ensemble
- Carte
- Chaîne
- n'importe quel objet avec Symbol.iterator
const iterable = {}
iterable[Symbol.iterator] = function* () {
yield 1
yield 2
yield 3
}
html`${repeat(iterable, renderItem)}`Étant donné que le modèle Markup ne gère pas le rendu de tels objets (à l'exception du tableau), il s'agit d'un avantage supplémentaire dans l'utilisation de repeat. Vous n'avez pas à vous soucier de la conversion de données en tableau uniquement pour pouvoir itérer et restituer.
La fonction de rappel sera toujours appelée avec les entrées et l'index.
const employeesSalary = {
'john doe': 30000,
'jane doe': 54000,
}
html`${repeat(employeesSalary, ([name, salary], index) => html`...`)}`État vide
Le repeat consomme également un troisième argument facultatif qui est une fonction qui sera appelée pour renvoyer ce qu'il faut restituer lorsque les données sont vides.
html`${repeat(todos, renderTodo, () => html`<p>No todos yet!</p>`)}`Clés et options
Par défaut, repeat utilise les éléments de la liste eux-mêmes comme clés d'identité pour suivre les mises à jour. Si vos éléments sont des objets ou si vous souhaitez les suivre grâce à un identifiant unique, vous pouvez plutôt passer un objet options comme troisième argument :
const options = {
key: (todo, index) => todo.id,
empty: () => html`<p>No todos yet!</p>`,
}
html`${repeat(todos, renderTodo, options)}`L'objet options prend en charge les propriétés suivantes :
key(fonction) : une fonction de sélection qui renvoie une clé unique pour chaque élément. Fortement recommandé pour les listes dynamiques dans lesquelles les éléments peuvent être réorganisés, ajoutés ou supprimés.empty(fonction) : une fonction renvoyant le modèle ou le nœud à restituer lorsque la collection est vide.
Rendu de liste paresseux
Pour optimiser les listes comportant un grand nombre d'éléments complexes, vous pouvez combiner l'utilitaire repeat avec l'utilitaire visible. Cela diffère le rendu des éléments de liste hors écran jusqu'à ce qu'ils soient sur le point de défiler :
import { html, repeat, visible } from '@beforesemicolon/markup'
html`
<ul>
${repeat(
todos,
(todo, index) =>
visible(
() => html`<todo-item item="${todo}"></todo-item>`,
html`<li class="placeholder">Loading...</li>`,
{ eager: index < 10 } // render first 10 immediately
),
{ key: (todo) => todo.id }
)}
</ul>
`