Intro


En esta ocasión vamos a ver como vincular y renderizar una lista HTML desde un array de datos de nuestro data(). La pregunta es: ¿cómo mostramos ese array como una lista HTML?

[js title=»app.js» highlight=»5″]
const app = Vue.createApp({
data() {
return {

games: [‘Grand Turismo’, ‘FIFA’, ‘GTA’]
}
}
})
[/js]

Recorrer Array de Datos (v-for)


Vamos a empezar creando una lista desordenada en nuestro index.html. En la etiqueta li es donde vamos a añadir otra directiva de Vue: v-for

[html title=»index.html»]
<ul>
<li v-for="game in games">{{ game }}</li>
</ul>
[/html]

Dentro de la expresión v-for escribimos game in games. Aquí, games nos referimos al array en nuestro data() y game es un alias para el elemento actual del array en el que nos encontramos, mientras lo recorremos para imprimir un nuevo li.


Cada li mostrará cada elemento del array porque dentro escribimos la expresión: {{ game }} que imprime cada juego.

Si comprobamos nuestra App en el navegador veremos la lista de juegos renderizada correctamente.



Pero, ¿como funciona la directiva v-for?

Recorrer array de objetos (v-for)


Vamos a completar nuestro array con objetos en lugar de solo nombres:

[js title=»app.js» highlight=»5″]
const app = Vue.createApp({
data() {
return {

games: [
{
id: 1,
name: "Grand Turismo",
score: 87,
},
{
id: 2,
name: "FIFA",
score: 65,
},
{
id: 3,
name: "GTA",
score: 90,
}
],
}
}
})
[/js]

Ahora tenemos un array que contiene un objeto para cada uno de los games. Cada juego contiene un id, un name y un score. En la siguiente tarea, usaremos el score para imprimirlo en cada game, y el id para ayudar a Vue a realizar un seguimiento de los elementos de nuestra lista HTML.

[html title=»index.html»]
<ul>
<li v-for="game in games" :key="game.id">
{{ game.name }} – {{ game.score }}
</li>
</ul>
[/html]

Fíjate como estamos usando la «dot notation» para imprimir cada game a medida que recorremos el array de games. Pero, ¿qué hace el atributo :key?

Atributo :key Esencial en los elementos de una lista


Al añadir el atributo :key="game.id", usamos la abreviatura de v-bind para vincular el id del game al atributo :key. Esto le da a cada elemento del DOM una clave única para que Vue pueda captar el elemento y no perderlo de vista a medida que las cosas se actualizan dentro de la App.

Esto proporciona algunas mejoras de rendimiento, y más adelante, si estás haciendo algo como animar los elementos, te darás cuenta que el atributo :key ayuda a Vue a administrar de manera efectiva sus elementos a medida que se mueven por el DOM.

Intro


Vamos a hablar sobre el «renderizado condicional» de HTML. ¿Y esto qué es? Pues la posibilidad de mostrar un trozo de HTML según una condición JS, así de simple.

En nuestro caso vamos a mostrar un texto (Conectado|Desconectado) basado en una nueva variable que crearemos en nuestro data(). Como siempre Vue nos ayuda a ello de una manera muy simple, otra vez a través de unas cuantas directivas, en este caso serán v-if, v-else y v-else-if

Directiva v-if


Vamos a empezar por añadir a nuestro index.html dos etiquetas p cada una con un texto diferente (conectado, desconectado).

[html title=»index.html» firstline=»17″ highlights=»19,20″]
<div class="player-info">
<h1>{{ player }}</h1>
<p>Conectado</p>
<p>Desconectado</p>
</div>
[/html]

Mostrar una u otra dependerá de la variable isOnline que añadiremos a nuestro data()

[js title=»app.js» hightlight=»6″]
const app = Vue.createApp({
data() {
return {
player: ‘Héctor Menduíña Hermelo’,
imgSrc: ‘./assets/img/avatar-1.png’,
isOnline: true
}
}
})
[/js]

Podemos añadir la directiva v-if a un elemento para decidir si lo mostramos o no dependiendo de una condición JS. En este caso nuestra variable isOnline.

[html title=»index.html» firstline=»19″]
<p v-if="isOnline">Conectado</p>
[/html]

Esa linea quiere decir que esa etiqueta p solo se renderizará en caso que isOnline sea verdadera.

La magia viene aquí, con v-if podemos combinar v-else para mostrar otro HTML cuando isOnline sea falsa.

[html title=»index.html» firstline=»19″]
<p v-if="isOnline">Conectado</p>
<p v-else>Desconectado</p>
[/html]

Si cambiamos el valor de la variable isOnline = false veremos que el texto renderizado será «Desconectado»

v-if vs v-show


No siempre se necesita emparejar v-if con v-else. Hay infinidad de casos donde no se suele necesitar v-else. En estos casos, suele ser mejor opción utilizar la directiva v-show.

[html title=»index.html»]
<p v-show="isOnline">Conectado</p>
[/html]

La directiva v-show su utiliza para intercambiar (mostrar/ocultar) la visibilidad de un elemento en lugar de añadir y eliminar el elemento al DOM como hace v-if.

Esto es una consecuencia importante, como puedes imaginar, por motivos de performance, es más eficaz v-show cuando es algo que se muestra y oculta con mucha frecuencia. Al usar v-show el HTML se renderiza siempre en el DOM, pero se oculta con un estilo en linea display: none; que Vue añade por nosotros (puedes comprobarlo inspeccionando el elemento en el navegador).

v-else-if


Vamos a ver como podemos encadenar capas de lógica a nuestro v-if/v-else.

Vamos a cambiar la variable isOnline por status que tendrá dos propiedades: isOnline y coverage para simular la cantidad de cobertura del player.

De esta manera, como ahora nuestra condición coverage es un integer, podemos utilizar algo más de lógica en nuestra expresión JS.

[js title=»app.js» hightlight=»6-9″]
const app = Vue.createApp({
data() {
return {
player: ‘Héctor Menduíña Hermelo’,
imgSrc: ‘./assets/img/avatar-1.png’,
status: {
isOnline: true,
coverage: 83
}
}
}
})
[/js]

[html title=»index.html» firstline=»21″]
<p v-if="status.coverage > 80">Buena conexión</p>
<p v-else-if="status.coverage <= 80 && status.coverage > 30">Normal</p>
<p v-else>Mala conexión</p>
[/html]

La directiva v-else-if nos da una capa intermedia de lógica. Dependiendo del valor de status.coverage mostraremos un HTML u otro. El resultado final después de esta lección debería ser algo como esto (ver imagen).


Vamos a ver ahora como enlazar atributos a nuestras etiquetas HTML. Vamos a ver como enlazar el src de una etiqueta img con una propiedad de nuestro data(). Esto quiere decir que cuando el valor enlazado al src cambie, nuestra imagen se actualizará en el DOM.

Preparamos el proyecto

Vamos a cambiar un poco nuestra estructura del proyecto. Para ello vamos a crear una carpeta en nuestro proyecto para los assets, la cual contendrá por el momento, otra carpeta que llamaremos img con un par de imágenes (las que queráis). También añadiremos un styles.css que nos hará falta en el futuro. La estructura de carpeta debería quedar algo así (ver imagen). También vamos a cambiar un poco nuestro index.html. Quedaría así (ver código, marcadas las lineas que cambiaron)

[html title=»index.html» firstline=»1″ highlight=»7,12-21″]
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>Introducción a Vue 3 – Coding Around the World!</title>
<!– Importar Estilos –>
<link rel="stylesheet" href="./assets/styles.css" />
<!– Importar Vue.js –>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<div class="player">
<div class="player-avatar">
<!– La imagen va aqui–>
</div>
<div class="player-info">
<h1>{{ player }}</h1>
</div>
</div>
</div>

<!– Vue App –>
<script src="./app.js"></script>

<!– Mount Vue App –>
<script>
const mountedApp = app.mount("#app")
</script>
</body>
</html>
[/html]

Añadir una imagen a nuestro data


Ahora que ya tenemos la imagen que queremos mostrar en nuestra ruta: './assets/img/avatar-1.png'  lo único que tenemos que hacer es crear una nueva propiedad imgSrc con nuestra imagen.

[js title=»app.js» highlight=»5″]
const app = Vue.createApp({
data() {
return {
player: ‘Héctor Menduíña Hermelo’,
imgSrc: ‘./assets/img/avatar-1.png’
}
}
})
[/js]

Una vez hecho esto estamos preparados para poder añadir la etiqueta img en nustro HTML.

[html]
<div class="player-avatar">
<img src="imgSrc">
</div>
[/html]

Enlazamos el src de la etiqueta con nuestra variable en el imgSrc pero por el momento esto no  hace nada. Vue todavía no sabe que nosotros queremos enlazar ambas. ¿Cómo se lo decimos a Vue?

Intro a enlaces de atributos


Para enlazar un atributo de una etiqueta HTML con un valor del data() de nuestra App vamos a usar una de las muchas directivas que Vue trae incorporadas llamada v-bind

[html]
<img v-bind:src="imgSrc">
[/html]

De esta manera creamos un enlace «reactivo» entre el atributo src de la etiqueta img y nuestra propiedad imgSrc. Ahora ya podemos abrir nuestro index.html en el navegador y comprobar si esto es verdad. Debería salir algo similar a esto:


Vamos a ver como funciona v-bind


¿Cómo funciona exactamente? Usamos la directiva v-bind para vincular dinámicamente el atributo src con el valor que va entre comillas "imgSrc". Esto lo que hace es decirle a Vue que tiene que evaluar el valor del src como una expresión de JS.

Esto quiere decir que gracias al sistema de reactividad de Vue si cambiamos el valor de nuestra propiedad imgSrc en el data() y abrimos el index.html en el navegador veremos que nuestra imagen se ha actualizado correctamente.

Usar v-bind es algo muy normal y recurrido en cualquier app hecha con Vue, por lo tanto nos ofrece un atajo para simplificar esto, y es sustituir v-bind por solo : . Como te puedes imaginar hay muchos atributos HTML diferentes tales como class, href, type, etc. Todos los atributos HTML pueden ser enlazados mediante v-bind o :

[html]
<img :src="imgSrc" :class="imgClass">
<input :type="inputType" />
<a :href="hrefLink">
[/html]

Intro


¿Estás preparado? Vamos a empezar de la manera más simple y con el mínimo código posible. Un index.html  y un app.js (L17). Con estos dos ficheros tendremos suficiente para empezar (en un futuro añadiremos un styles.css) (L7). La manera más simple de empezar a usar Vue 3 como librería es copiar de la documentación oficial el link a la CDN (solo para aprender, no para producción) e importarlo en nuestro index.html (L9) como un script.

Al final del fichero tenemos la importación al script de nuestra app.js que de momento solo contendrá una constante.

[html title=»index.html» firstline=»1″ highlight=»7,9, 17″]
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>Introducción a Vue 3 – Coding Around the World!</title>
<!– Importar Estilos –>
<link rel="stylesheet" href="./styles.css" />
<!– Importar Vue.js –>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<h1>Nombre del jugador</h1>
</div>

<!– App –>
<script src="./app.js"></script>
</body>
</html>
[/html]

[js title=»app.js»]
const player = "Héctor Menduíña Hermelo"
[/js]

Si te fijaste bien, en el index.html tenemos una etiqueta h1 que dice donde deberíamos mostrar el nombre del jugador. La pregunta es, ¿cómo utilizar Vue para mostrar la variable player?

Creando una Vue App


Para poder mostrar nuesta info dentro de nuestro HTML lo primero que necesitamos es crear una Vue App. Para ello cambiamos el código en nuestro app.js de la siguiente manera:

[js title=»app.js»]
const app = Vue.createApp({})
[/js]

Com ves solo necesitamos el método createApp({}) que recibe como argumento un objeto. Ese será el objeto que nos permita configurar nuestra App. Añadiremos la propiedad data(), que como su propio nombre indica será donde almacenaremos los datos de nuestra App. Esta debe ser una función que retorna otro objeto. Añadiremos nuestro player como una propiedad del data().

[js title=»app.js»]
const app = Vue.createApp({
data() {
return {
player: ‘Héctor Menduíña Hermelo’
}
}
})
[/js]

Montando nuestra Vue App


Bien, una vez tenemos «creada» nuestra App, necesitamos decirle a nuestro DOM donde la queremos montar. Pues Vue también nos facilita esta tarea. Para ello vamos a añadir otra etiqueta script al final de nuestro index.html. (L. 20)

[html title=»index.html» firstline=»1″ highlight=»12, 20-22″]
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>Introducción a Vue 3 – Coding Around the World!</title>
<!– Importar Estilos –>
<link rel="stylesheet" href="./styles.css" />
<!– Importar Vue.js –>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<h1>Nombre del jugador</h1>
</div>

<!– Vue App –>
<script src="./app.js"></script>

<!– Mount Vue App –>
<script>
const mountedApp = app.mount("#app")
</script>
</body>
</html>
[/html]

Como ves hacemos uso de la variable app que hace referencia a nuestra App que acabamos de crear en el app.js. Llamaremos al método mount(), el cual necesita en selector de DOM como argumento. En nuestro caso será el "#app" (L.12) el que  nos permite conectar nuestra Vue App con nuestro DOM de una manera muy simple.

Mostrando datos


Una vez tenemos nuestra Vue App creada, importada y montada en nuestro DOM, podemos empezar a mostrar los datos que tenemos en ella. Para renderizar nuestra propiedad player dentro de la etiqueta h1, escribimos lo siguiente en nuestro index.html:

[html title=»index.html» firstline=»12″ tabsize=»2″]
<div id="app">
<h1>{{ player }}</h1>
</div>
[/html]

Sí ahora abrimos nuestro index.html en el navegador veremos que el nombre de nuestra propiedad player se debería mostrar en la etiqueta h1. ¿Magia? vamos a entender qué esta pasando para que esto funcione así.

Entendiendo la instancia Vue


Al crear nuestra Vue App, le pasamos un objeto de configuración, lo que nos permite añadir algunas propiedades opcionales para configurar la app. Al llamar a createApp() se crea nuestra instancia Vue, el corazón de nuestra App, lo que lo controla todo.

[js title=»app.js»]
const app = Vue.createApp({Options Object})
[/js]

Al importar nuestra App en el index.html y montarla en el DOM, lo que hicimos fue «enchufarla», esto quiere decir que nuestro HTML ahora tendrá linea directa con nuestra App, pudiendo acceder a todas las opciones como su data().



¿Qué hacen las doble llaves (curly brace syntax)? Vamos a imaginar que es una linea directa con nuestra App Vue.

El diálogo podría ser algo así:

  • HTML: ¿cuál es el valor de la propiedad player?
  • App: Héctor Menduíña Hermelo

Cuando la página se renderiza lo que vemos es «Héctor Menduíña Hermelo».

Si no estas familiarizado con la sintaxis de doble llave ({{ player }}) lo que nos permite es escribir expresiones JavaScript válidas dentro de nuestro HTML, algo muy útil.

Reactividad en Vue


¿Qué pasaría si cambiamos el valor de player de «Héctor Menduíña Hermelo» a «Michael Jordan»?

Debido a como funciona Vue, la expresión de la tag h1 que depende de la propiedad player recibiría automáticamente el nuevo valor y el DOM se actualizaría para mostrar «Michael Jordan».

Eso es porque Vue es reactivo.Entre bambalinas, Vue tiene un completo sistema de reactividad que maneja las actualizaciones del DOM. Cuando un valor del data() cambia, cualquier lugar del que dependa dentro de la App se actualizará automáticamente. Nosotros no tenemos que hacer nada, Vue lo hace por nosotros :). Más adelante crearé algún post hablando sobre este tema.