Crea tu primer componente con Vue.js (para dummies)
Tags: javascript, vue, webdev, spanish
Published: 2020-06-29 16:59:45

Vue.js a la cabeza de su creador Evan You ha llegado para quedarse estableciéndose de manera muy firme entre la comunidad de desarrollo web front-end. 
El equipo de Vue.js define a su herramienta como un framework progresivo para el desarrollo de interfaces de usuario. 
Este post es netamente práctico así que evitaré hablar de conceptos o definiciones abundantes.
## **¿Qué es un Web Component?**
Un Web Component es una característica muy poderosa que nos provee Vue.js permitiendo encapsular código reutilizable. 
Al momento de comprender una nueva definición en software me gusta hacer analogías, podríamos ver a un componente como una pieza de Lego, tiene características propias como un tamaño, un color, una forma y con ellas podríamos construir objetos basados en nuestra imaginación; algo similar pasa con un Web Component, en su interior almacena código que tendrá un comportamiento especifico en nuestra web.


![lego](https://s03.s3c.es/imag/_v0/3504x2336/e/5/d/pieza-lego.jpg)

> *Imagina a un Web Component como una pieza de Lego*

En nuestra analogía al unir de manera creativa varios legos podríamos construir por ejemplo un coche de juguete, un robot, etc. Igualmente, al unir varios componentes podríamos formar una aplicación web sencilla o bastante compleja. 


![auto-lego](https://i.pinimg.com/736x/b1/76/ce/b176ceecb5dbdd6ce141d70c3e7d35a9.jpg)

> *Uniendo legos se puede crear por ejemplo un coche de juguete, de la misma manera uniendo varios web components podemos crear aplicaciones web.* 

## **Tipos de Web Components en Vue.js**
Vue cuenta con dos tipos de componentes:

* **Componentes Locales:** son archivos con extensión `.vue` que el navegador por sí solo no puede comprender y por ende es necesario del uso de herramientas como Web Pack. Son bastante útiles para una aplicación web escalable por su sencillez de mantenimiento. 

* **Componentes Globales:** No necesitan archivos con extensión `.vue`, pueden ser accedidos desde cualquier parte del código pero no se aconseja su uso en aplicaciones web grandes por razones de mantenimiento. Son los más sencillos de aprender y los que veremos en este tutorial. 

## **Vamos al código** :computer:
### **Preparamos los archivos necesarios**
* Creamos un archivo `index.html` y otro `app.js`.
* En `index.html` importamos el CDN de Vue.js (aconsejo usar la versión de desarrollo) y también enlazamos nuestro `app.js`. Tendríamos algo así:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="app.js"></script>
</body>
</html>
```

* En `app.js` creamos nuestra instancia de Vue, estableciendo el alcance de la misma con un `id`, en mi caso `id=main`.

```javascript
//app.js
const vm = new Vue({
    el: '#main'
});
```

* Establecemos en `index.html` un `div` con dicho alcance. 

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

<div id="main">
 //alcance de Vue
</div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="app.js"></script>
</body>
</html>
```
## **Sintaxis básica de un componente**

```javascript
Vue.component('nombre-del-componente',{
    props:['propiedades del componente'], // usualmente se usa un array
    template: 'código HTML del componente'
});
```

### **Creación del componente**
Ahora que tenemos nuestros archivos listos proseguimos a crear nuestro componente:

* En `app.js` escribimos lo siguiente:

```javascript
Vue.component('picture-card',{
    props:['title', 'picture_url'],
    template: '#template-picture'
});

const vm = new Vue({
    el: '#main'
});

```
Donde:
:small_blue_diamond: `Vue.component({})` declara un nuevo componente.
:small_blue_diamond: `picture-card` es el nombre del componente.
:small_blue_diamond: el arreglo `props` engloba todas las propiedades que deseamos que tenga nuestro componente, en nuestro caso un `title` y una `picture_url`.
:small_blue_diamond: será la estructura HTML del componente (por motivos de clean code será declarado en `index.html`)

> *`props` puede ser declarado como objeto y puede existir n propiedades por componente.*

## **¿Qué son las props?**
Imaginemos una etiqueta `<img>` por si sola no puede hacer su trabajo, necesita obligatoriamente de su propiedad `src` al cual se le pasa una url absoluta o relativa, también puede tener su propiedad `alt` que contiene un texto alternativo si por alguna razón la imagen no carga. `<img>` es una etiqueta nativa de HTML, `src` y `alt` son atributos nativos; en nuestro caso tenemos un componente <picture-card> personalizado con sus `props` 'title' y 'picture_url' personalizadas también. 

> *Un atributo de etiqueta en HTML se conoce como una props en Vue.js.*

* Ahora declaramos nuestro `template` en `index.html` y usamos nuestro componente `<picture-card>`

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <template id="template-picture">
        <div>
            <h1>{{title}}</h1>
            <img :src="picture_url" :alt="title" width="150">
        </div>
    </template>
    <div id="main">
        <picture-card title="Hello Word" picture_url="https://images.pexels.com/photos/4394807/pexels-photo-4394807.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"></picture-card>
        <picture-card title="Mi title!!" picture_url="https://images.pexels.com/photos/3841338/pexels-photo-3841338.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"></picture-card>
        <picture-card title="Take it!!" picture_url="https://images.pexels.com/photos/1570264/pexels-photo-1570264.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"></picture-card>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 
    <script src="app.js"></script>
</body>
</html>
```

<iframe height="265" style="width: 100%;" scrolling="no" title="Componentes con Vue" src="https://codepen.io/dux-soft/embed/ExPXmYO?height=265&theme-id=dark&default-tab=html,result" frameborder="no" allowtransparency="true" allowfullscreen="true">
Puedes ver el código ejecutandose en el siguiente link: <a href='https://codepen.io/dux-soft/pen/ExPXmYO'>Componentes con Vue</a>
</iframe>

## **Mejorando el código**
En nuestro ejemplo creamos exitosamente un componente llamado `<picture-card>` con sus respectivas propiedades, pero imaginemos el escenario donde necesitamos utilizar nuestro componente 100 veces, sería mucho trabajo y poco práctico llamar 100 veces al mismo componente, para solucionar esto podríamos usar la directiva `v-for` de la siguiente manera: 

En `app.js` creamos un array de objetos llamado `pictures`.

```javascript
Vue.component('picture-card',{
    props:['title', 'picture_url'],
    template: '#template-picture'
});

const vm = new Vue({
    el: '#main',
    data:{
        pictures:[
            {id:1, title:'Title 1', picture_url:'https://images.pexels.com/photos/1570264/pexels-photo-1570264.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940'},
            {id:2, title:'Title 2', picture_url:'https://images.pexels.com/photos/4394807/pexels-photo-4394807.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940'},
            {id:3, title:'Title 3', picture_url:'https://images.pexels.com/photos/3841338/pexels-photo-3841338.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940'}
        ]
    }
});
```

Con la directiva `v-for` recorremos el obejeto `picture` y con `v-bind` accedemos a las propiedades el objeto enlazándolas dinámicamente. 

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <template id="template-picture">
        <div>
            <h1>{{title}}</h1>
            <img :src="picture_url" :alt="title" width="150">
        </div>
    </template>

    <div id="main">
        <picture-card v-for="(picture, index) in pictures" :key="index" :title="picture.title" :picture_url="picture.picture_url">
        </picture-card>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="app.js"></script>
</body>
</html>
```
El resultado sería el siguiente:

![image](https://raw.githubusercontent.com/crisdux/basic-component-vue2/master/title.png)

Te dejo el link al repositorio del proyecto en Github:  https://github.com/crisdux/basic-component-vue2

## **Referencias**
* https://www.youtube.com/watch?v=6_LrK6Ky78k
* https://es.vuejs.org/v2/guide/components.html#ad

---

## **Conclusiones**
![gif](https://media.giphy.com/media/5z7CHArtb4AlA5hV7l/giphy.gif)
Despueés de aprender a crear tu primer componente en Vue se pueden llegar a las siguientes conclusiones:

* La programación web basada en componentes es bastante importante en frameworks front-end modernos como Vue, React y Angular.
* Un componente es como una pieza de lego.
* Encapsular el código en porciones independientes y reutilizables es bastante útil y optimo
* Vue permite crear componentes web de una manera bastante ituitiva y sencilla de comprender.
* Las directivas en Vue son bastante poderosas.