🕓 Hora de Refactorizar
Ya progresamos bastante en cuanto a los conceptos de Vue y como aplicarlos en una situación "real". El problema es que actualmente estamos concentrando mucha información y responsabilidad en un solo lugar, el componente Search
.
Esto va un poco en contra de la filosofía Vue de hacer los componentes ASAP, as small as possible (tan chicos como sea posible). Vamos a complicar un poco las cosas y modularizar nuestra aplicación en componentes mas pequeños.
Artist.vue
Lo primero que vamos a refactorizar es el template que estamos renderizando por cada elemento en la propiedad results
. Creamos dentro de src/components
un nuevo archivo .vue
con el nombre Artist.vue
➡️ src/components/Artist.vue
- En la parte de HTML del nuevo componente vamos a cortar el contenido que tenemos dentro del
v-for
enSearch.vue
. El HTML deArtist.vue
debe quedar de la siguiente manera:
<template lang="html">
<li>
<div class="artist">
<p>{{ artist.name }}</p>
<!-- ⚠️ En este caso agrego también un v-if para prevenir errores ya que la propiedad images puede venir vacia -->
<img v-if="artist.images.length" :src="artist.images[0].url" :alt="artist.name">
<p v-else>🚫 🌅</p>
</div>
</li>
</template>
Pueden notar que renombré algunas variables para que tenga un significado mas semántico. Lo que antes era
r
ahora esartist
. También cambie la clase"result"
del<div>
por la clase"artist"
- Luego vamos a crear la parte JS. El contenido es bastante breve, lo único que necesitamos es definir las
props
necesarias. Recordemos que la manera que tiene un componente padre de enviar información al hijo es usando propiedades definidas en el objetoprops
del componente hijo. Estas funcionan de la misma manera que las propiedadesdata
con la particularidad que el componente hijo NO puede modificarlas. Al momento de usar el componente estas propiedades se reflejan como atributos HTML. En nuestro caso solo vamos a definir una propiedad con el nombre deartist
, esta nos va a permitir que el objeto padre nos pase un objeto con toda la información del artista (usando un atributo HTML).
<script>
export default {
name: 'Artist',
props: {
artist: {
type: Object, // Tipo de dato de la propiedad
required: true // Establecemos la propiedad como obligatoria
}
}
}
</script>
- también podemos aprovechar para mover todo el CSS ligado a esa parte del template y de esta manera mantener la consistencia. Si el CSS pertenece al componente en todos los lugares donde lo utilice lo voy a poder visualizar de la misma manera.
<style scoped>
li {
display: flex;
justify-content: center;
padding: 0.2em;
border: 1px solid #42b983;
margin: 0.2em;
width: 200px;
height: 200px;
}
.artist {
display: flex;
flex-direction: column;
align-items: center;
}
img {
width: 100px;
height: 100px;
}
</style>
Search.vue
Tenemos que aplicar estos cambios al componente Search
.
Lo primero que debemos hacer es, en la parte JS, importar el componente
Artist
. Los import deben ir siempre ubicados al principio del archivo JS o al principio del tag<script>
Luego debemos indicarle a
Search
que puede disponer del componenteArtist
usando el objetocomponents
delvm
. (Esto lo hicimos enApp.vue
cuando implementamos elSearch.vue
)Por último debemos actualizar el HTML, borrar lo que movimos a
Artist.vue
y reemplazarlo por el nuevo markup. Esa parte del template debería quedarnos así:
<ul>
<artist v-for="r in results" :artist="r" :key="r.id"></artist>
</ul>
Ahora estamos aplicando la directiva v-for directamente sobre el componente <artist>
. A este componente le pasamos r
que representa cada uno de los resultados usando el atributo :artist
que definimos previamente.
Tengamos en cuenta que a la hora de usar propiedades es fundamental el uso de :
(o v-bind
). Si no los usamos en lugar de pasarle el objeto r
le estaríamos pasando un String
con valor letra ('r'
).
Por otro lado vemos otra propiedad llamada :key
. Esto es algo nativo de Vue que podemos agregar cada vez que usamos v-for
. Usando este atributo key le indicamos a Vue un valor unívoco para permitirle trackear los elementos del v-for
de manera mas óptima y precisa.
Finalizado esto, ya tenemos un código mas modularizado pero que no representa ningún cambio en funcionalidad o diseño. Nuestra aplicación debería seguir comportándose de la misma manera.
🤓 Extras
Aprovechando que estamos refactorizando podemos crear dos componentes para dividir la estructura de nuestra app y practicar un poco más. Les propongo crear un componente para representar el header de la aplicación y otro para el footer. A uno podemos ponerle Top.vue
y al otro Bottom.vue
. Una buena práctica es poner este tipo de componentes dentro de una carpeta layout
➡️ `src/components/layout.