Utilidad de repetición
La utilidad repeat es la forma recomendada por Markup de representar datos iterables o contenido repetido. Maneja cosas como el almacenamiento en caché y el seguimiento de la plantilla, lo que garantiza que los cambios en la lista solo se realicen en los elementos que los necesitan.
html`${repeat(todos, renderTodo)}`¿Por qué utilizar repetir?
Las plantillas Markup ya manejan matrices, pero como cualquier otro valor inyectado, Markup rastrea todo y no sus elementos individuales.
const [todos, updateTodos] = state([])
html`${() => todos().map(renderTodo)}`.render(document.body)
updateTodos((prev) => [
...prev,
{
name: 'Go to gym',
status: 'pending',
},
])El código anterior funcionará bien en cuanto a representar una lista. El problema se vuelve evidente cuando un solo elemento cambia, se agrega o se elimina. Esto se debe a que se volverá a llamar a la función generando una nueva lista de contenido para renderizar. Si Markup ve una nueva lista, volverá a representar todo.
La mejor manera es no mapear dinámicamente la lista en el renderizado sino en la creación para que Markup siempre tenga las cosas que desea renderizar para que pueda verificar si es diferente a antes o no.
const [todos, updateTodos] = state([])
html`${todos}`.render(document.body)
updateTodos((prev) => [
...prev,
renderTodo({
name: 'Go to gym',
status: 'pending',
}),
])Esto es exactamente lo que la utilidad repeat hace por usted con solo tomar los datos y la función de renderizado.
Números
El asistente repeat acepta un número entre muchas cosas. Este número representa la cantidad de veces que desea que se llame a la función de representación de devolución de llamada.
html`${repeat(3, html`<spa></span>`)}`La función de devolución de llamada se llamará con números del 1 al número que proporcionó junto con los índices.
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>Iterables y literales de objetos
Además, repeat puede consumir cualquier objeto literal u objeto iterable y esto incluye:
- matriz
- conjunto
- Mapa
- cuerda
- cualquier objeto con Symbol.iterator
const iterable = {}
iterable[Symbol.iterator] = function* () {
yield 1
yield 2
yield 3
}
html`${repeat(iterable, renderItem)}`Dado que la plantilla Markup no maneja la representación de dichos objetos (excepto Array), esta es una ventaja adicional al usar repeat. No tiene que preocuparse por convertir ningún dato a Array solo para poder iterar y renderizar.
La función de devolución de llamada siempre será llamada con las entradas y el índice.
const employeesSalary = {
'john doe': 30000,
'jane doe': 54000,
}
html`${repeat(employeesSalary, ([name, salary], index) => html`...`)}`Estado vacío
El repeat también consume un tercer argumento opcional, que es una función que se llamará para devolver qué representar cuando los datos estén vacíos.
html`${repeat(todos, renderTodo, () => html`<p>No todos yet!</p>`)}`Teclas y opciones
De forma predeterminada, repeat utiliza los elementos de la lista como claves de identidad para realizar un seguimiento de las actualizaciones. Si sus elementos son objetos o desea rastrearlos mediante un identificador único, puede pasar un objeto de opciones como tercer argumento:
const options = {
key: (todo, index) => todo.id,
empty: () => html`<p>No todos yet!</p>`,
}
html`${repeat(todos, renderTodo, options)}`El objeto de opciones admite las siguientes propiedades:
key(función): una función selectora que devuelve una clave única para cada elemento. Altamente recomendado para listas dinámicas donde los elementos se pueden reordenar, agregar o eliminar.empty(función): una función que devuelve la plantilla o el nodo para representar cuando la colección está vacía.
Representación de lista diferida
Para optimizar listas con una gran cantidad de elementos complejos, puede combinar la utilidad repeat con la utilidad visible. Esto pospone la representación de elementos de la lista fuera de la pantalla hasta que estén a punto de desplazarse para aparecer en la vista:
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>
`