La representación de listas es una de las prácticas más utilizadas en el desarrollo web front-end. La representación dinámica de listas se usa a menudo para presentar una serie de información agrupada de manera similar en un formato conciso y fácil de usar para el usuario. En casi todas las aplicaciones web que usamos, podemos ver listas de contenido en numerosas áreas de la aplicación.
En este artículo reuniremos una comprensión de Vue v-for
Directiva en la generación de listas dinámicas, así como pasar por algunos ejemplos de por qué el key
El atributo debe usarse al hacerlo.
Dado que explicaremos las cosas detalladamente a medida que comencemos a escribir el código, este artículo asume que tendrá muy poco o ningún conocimiento con Vue (y/u otros marcos de JavaScript).
Estudio de caso: Twitter
vamos a usar Gorjeo como caso de estudio para este artículo.
Cuando iniciamos sesión y en la ruta de índice principal de Twitter, se nos presenta una vista similar a esta:
En la página de inicio, nos hemos acostumbrado a ver una lista de tendencias, una lista de tweets, una lista de seguidores potenciales, etc. El contenido que se muestra en estas listas depende de una multitud de factores: nuestro historial de Twitter, a quién seguimos, nuestros gustos, etc. Como resultado, podemos decir que todos estos datos son dinámicos.
Aunque estos datos se obtienen dinámicamente, la forma en que se muestran sigue siendo la misma. Esto se debe en parte al uso componentes web reutilizables.
Por ejemplo; podemos ver la lista de tweets como una lista de solo tweet-component
elementos. podemos pensar en tweet-component
como un caparazón que toma datos de todo tipo, como el nombre de usuario, el identificador, el tweet y el avatar, entre otras piezas, y que simplemente muestra esas piezas en un marcado coherente.
Digamos que queremos representar una lista de componentes (por ejemplo, una lista de tweet-component
artículos) basados en una gran fuente de datos obtenida de un servidor. En Vue, lo primero que debe venir a la mente para lograr esto es el v-for
directiva.
La directiva v-for
El v-for
La directiva se utiliza para representar una lista de elementos basada en una fuente de datos. La directiva se puede utilizar en un elemento de plantilla y requiere una sintaxis específica del tipo:
Veamos un ejemplo de esto en la práctica. Primero, supondremos que ya hemos obtenido una colección de datos de tweets:
const tweets = [
{
id: 1,
name: 'James',
handle: '@jokerjames',
img: 'https://semantic-ui.com/images/avatar2/large/matthew.png',
tweet: "If you don't succeed, dust yourself off and try again.",
likes: 10,
},
{
id: 2,
name: 'Fatima',
handle: '@fantasticfatima',
img: 'https://semantic-ui.com/images/avatar2/large/molly.png',
tweet: 'Better late than never but never late is better.',
likes: 12,
},
{
id: 3,
name: 'Xin',
handle: '@xeroxin',
img: 'https://semantic-ui.com/images/avatar2/large/elyse.png',
tweet: 'Beauty in the struggle, ugliness in the success.',
likes: 18,
}
]
tweets
es una colección de tweet
objetos con cada tweet
que contiene detalles de ese tweet en particular: un identificador único, el nombre/identificador de la cuenta, el mensaje del tweet, etc. Ahora intentemos usar el v-for
Directiva para generar una lista de componentes de tweet basados en estos datos.
En primer lugar, crearemos la instancia de Vue, el corazón de la aplicación Vue. Montaremos/adjuntaremos nuestra instancia a un elemento DOM de id app
y asignar el tweets
colección como parte del objeto de datos de la instancia.
new Vue({
el: '#app',
data: {
tweets
}
});
Ahora seguiremos adelante y crearemos un tweet-component
esa hora v-for
directiva utilizará para representar una lista. Usaremos el global Vue.component
constructor para crear un componente llamado tweet-component
:
Vue.component('tweet-component', {
template: `
<div class="tweet">
<div class="box">
<article class="media">
<div class="media-left">
<figure class="image is-64x64">
<img :src="https://css-tricks.com/list-rendering-and-vues-v-for-directive/tweet.img" alt="Image">
</figure>
</div>
<div class="media-content">
<div class="content">
<p>
<strong>{{tweet.name}}</strong> <small>{{tweet.handle}}</small>
<br>
{{tweet.tweet}}
</p>
</div>
<div class="level-left">
<a class="level-item">
<span class="icon is-small"><i class="fas fa-heart"></i></span>
<span class="likes">{{tweet.likes}}</span>
</a>
</div>
</div>
</article>
</div>
</div>
`,
props: {
tweet: Object
}
});
Algunas cosas interesantes a tener en cuenta aquí.
- El
tweet-component
espera untweet
accesorio de objeto como se ve en el requisito de validación de accesorios (props: {tweet: Object}
). Si el componente se renderiza con untweet
prop que no es un objeto, Vue emitirá advertencias. - Vinculamos las propiedades del accesorio de objeto de tweet a la plantilla del componente con la ayuda de la sintaxis de Mustache:
{{ }}
. - El marcado del componente adapta el elemento Caja de Bulma, ya que representa un buen parecido con un tweet.
En la plantilla HTML, necesitaremos crear el marcado donde se montará nuestra aplicación Vue (es decir, el elemento con la identificación de app
). Dentro de este marcado, usaremos el v-for
Directiva para generar una lista de tweets. Ya que tweets
es la recopilación de datos sobre la que estaremos iterando, tweet
será un alias apropiado para usar en la directiva. En cada renderizado tweet-component
, también pasaremos el iterado tweet
objeto como accesorios para acceder a él en el componente.
<div id="app" class="columns">
<div class="column">
<tweet-component v-for="tweet in tweets" :tweet="tweet"/>
</div>
</div>
Independientemente de cuántos objetos de tweet más se introduzcan en la colección; o cómo cambiarán con el tiempo: nuestra configuración siempre mostrará todos los tweets de la colección con el mismo marcado que esperamos.
Con la ayuda de un CSS personalizado, nuestra aplicación se verá así:
Vea el Twitter Pen Simple Feed #1 por Hassan Dj (@itslit) en CodePen.
Aunque todo funciona como se esperaba, es posible que se nos solicite un consejo de Vue en la consola de nuestro navegador:
[Vue tip]: <tweet-component v-for="tweet in tweets">: component lists rendered with v-for should have explicit keys...
Es posible que no pueda ver la advertencia en la consola del navegador cuando ejecute el código a través de CodePen.
¿Por qué Vue nos dice que especifiquemos claves explícitas en nuestra lista cuando todo funciona como se esperaba?
llave
Es una práctica común especificar un atributo clave para cada elemento iterado dentro de un renderizado. v-for
lista. Esto se debe a que Vue usa el key
atributo para crear enlaces únicos para la identidad de cada nodo.
Expliquemos esto un poco más: si hubo cambios en la interfaz de usuario dinámica en nuestra lista (por ejemplo, el orden de los elementos de la lista se baraja), Vue optará por cambiar los datos dentro de cada elemento en lugar de mover los elementos DOM en consecuencia. Esto no será un problema en la mayoría de los casos. Sin embargo, en ciertos casos en los que nuestro v-for
list depende del estado del DOM y/o del estado del componente secundario, esto puede causar un comportamiento no deseado.
Veamos un ejemplo de esto. ¿Qué pasaría si nuestro componente de tweet simple ahora contuviera un campo de entrada que permitiría al usuario responder directamente al mensaje de tweet? Ignoraremos cómo se podría enviar esta respuesta y simplemente abordaremos el nuevo campo de entrada:
Incluiremos este nuevo campo de entrada en la plantilla de tweet-component
:
Vue.component('tweet-component', {
template: `
<div class="tweet">
<div class="box">
// ...
</div>
<div class="control has-icons-left has-icons-right">
<input class="input is-small" placeholder="Tweet your reply..." />
<span class="icon is-small is-left">
<i class="fas fa-envelope"></i>
</span>
</div>
</div>
`,
props: {
tweet: Object
}
});
Supongamos que queremos introducir otra función nueva en nuestra aplicación. Esta característica implicaría permitir al usuario mezclar aleatoriamente una lista de tweets.
Para hacer esto; primero podemos incluir un “Shuffle!” botón en nuestra plantilla HTML:
<div id="app" class="columns">
<div class="column">
<button class="is-primary button" @click="shuffle">Shuffle!</button>
<tweet-component v-for="tweet in tweets" :tweet="tweet"/>
</div>
</div>
Hemos adjuntado un detector de eventos de clic en el elemento de botón para llamar a un shuffle
método cuando se activa. En nuestra instancia de Vue; crearemos el shuffle
método responsable de barajar aleatoriamente los tweets
colección en la instancia. Usaremos el método _shuffle de lodash para lograr esto:
new Vue({
el: '#app',
data: {
tweets
},
methods: {
shuffle() {
this.tweets = _.shuffle(this.tweets)
}
}
});
¡Vamos a probarlo! Si hacemos clic en barajar un par de veces; Notaremos que los elementos de nuestro tweet se ordenan aleatoriamente con cada clic.
Vea el Pen Simple Twitter Feed #2 por Hassan Dj (@itslit) en CodePen.
Sin embargo, si escribimos alguna información en la entrada de cada componente, haga clic en barajar; notaremos que sucede algo peculiar:
Dado que no hemos optado por utilizar el key
atributo, Vue no ha creado enlaces únicos para cada nodo de tweet. Como resultado, cuando nuestro objetivo es reordenar los tweets, Vue adopta el enfoque de ahorro de mayor rendimiento para simplemente cambiar (o parchear) los datos en cada elemento. Dado que el estado DOM temporal (es decir, el texto ingresado) permanece en su lugar, experimentamos este desajuste no deseado.
Aquí hay un diagrama que nos muestra los datos que se parchean en cada elemento y el estado DOM que permanece en su lugar:
Para evitar esto; tendremos que asignar un único llave a cada tweet-component
representado en la lista. Usaremos el id
de un tweet
ser el identificador único ya que deberíamos decir con seguridad un tweet id
no debe ser igual a la de otro. Debido a que estamos usando valores dinámicos, usaremos el v-bind
directiva para vincular nuestra clave a la tweet.id
:
<div id="app" class="columns">
<div class="column">
<button class="is-primary button" @click="shuffle">Shuffle!</button>
<tweet-component v-for="tweet in tweets" :tweet="tweet" :key="tweet.id" />
</div>
</div>
Ahora, Vue reconoce la identidad del nodo de cada tweet; y así reordenará los componentes cuando tengamos la intención de barajar la lista.
Dado que cada componente de tweet ahora se mueve en consecuencia, podemos llevar esto un paso más allá y usar Vue transition-group
para mostrar cómo se están reordenando los elementos.
Para ello, añadiremos el transition-group
elemento como un envoltorio para el v-for
lista. Especificaremos un nombre de transición de tweets
y declarar que el grupo de transición debe ser representado como un div
elemento.
<div id="app" class="columns">
<div class="column">
<button class="is-primary button" @click="shuffle">Shuffle!</button>
<transition-group name="tweets" tag="div">
<tweet-component v-for="tweet in tweets" :tweet="tweet" :key="tweet.id" />
</transition-group>
</div>
</div>
Según el nombre de la transición, Vue reconocerá automáticamente si se han especificado transiciones/animaciones CSS. Dado que nuestro objetivo es invocar una transición para el movimiento de elementos en la lista; Vue buscará una transición CSS específica a lo largo de las líneas de tweets-move
(donde tweets
es el nombre dado a nuestro grupo de transición). Como resultado, introduciremos manualmente un .tweets-move
clase que tiene un tipo y tiempo de transición especificados:
#app .tweets-move {
transition: transform 1s;
}
Esta es una mirada muy breve a la aplicación de transiciones de lista. ¡Asegúrese de consultar los documentos de Vue para obtener información detallada sobre todos los diferentes tipos de transiciones que se pueden aplicar!
Nuestra tweet-component
los elementos ahora harán una transición adecuada entre ubicaciones cuando se invoque una reproducción aleatoria. ¡Darle una oportunidad! Escriba alguna información en los campos de entrada y haga clic en “¡Mezclar!” unas pocas veces.
Vea el Pen Simple Twitter Feed #3 por Hassan Dj (@itslit) en CodePen.
Bastante genial, ¿verdad? Sin el key
atributo, el elemento del grupo de transición no se puede usar para crear transiciones de lista ya que los elementos se parchean en su lugar en lugar de reordenarse.
Si el key
atributo siempre se utiliza? Se recomienda. Los documentos de Vue especifican que el atributo clave solo debe omitirse si:
- Intencionalmente, queremos la forma predeterminada de aplicar parches a los elementos por motivos de rendimiento.
- El contenido del DOM es bastante simple.
Conclusión
¡Y ahí lo tenemos! Esperemos que este breve artículo describa cuán útil es el v-for
directiva también proporciona un poco más de contexto de por qué la key
El atributo se usa a menudo. ¡Avíseme si tiene alguna pregunta/idea de cualquier tipo!
Si le gustó mi estilo de escritura y está potencialmente interesado en aprender a crear aplicaciones con Vue.js, es posible que le guste el libro. Fullstack Vue: la guía completa de Vue.js que ayudé a publicar! El libro cubre numerosas facetas de Vue, incluidas, entre otras, el enrutamiento, la administración de estado simple, el manejo de formularios, Vuex, la persistencia del servidor y las pruebas. Si estás interesado, puedes obtener más información en nuestra web, https://fullstack.io/vue.