DÍA 10 / 2018

VueJS para tod@s

Sin duda la popularidad de VueJS como librería frontend se da por su simplicidad y baja curva de aprendizaje; y además hace muy bien su trabajo: manipular datos, rápidamente. En este artículo presentaré una introducción simple a esta librería, además de aclarar varios conceptos que he observado durante el tiempo. Para leer este artículo necesitarás conocimiento básico de programación; si has hecho HTML, CSS y un poco de JavaScript será más que suficiente. Trataré de explicarlo lo más simple posible.


¿Qué es VueJS?

Es una librería JavaScript relativamente nueva (va en su versión 2.5 a la fecha y ya tiene un roadmap público hasta la versión 4), de código abierto y orientado a la manipulación de datos (reactiva). Sólo se enfoca en la vista, no se integra directamente con otros lenguajes backend sino que a través de API’s. Permite Server Side Rendering (SSR), manejo de estados con VueX, ruteo de vistas además de basarse en el estándar web de web components, permitiendo tener en un mismo componente (archivo) .vue el marcado HTML, los estilos CSS y las funcionalidades JS, todas encapsuladas en ese componente y permitiendo importar otros componentes hijos. Finalmente, el core es muy liviano (30kb aprox.) y desempeña muy bien en browsers móviles.

Un componente .vue

¿VueJS reemplaza jQuery?

¡NO! Esto he leído y escuchado mucho. Ambas librerías no son comparables, para nada. Es cierto, trabajan con la interfaz en el browser pero tienen diferentes fines. jQuery es una librería utilitaria, que ayudó mucho a nivelar el cross-browsing que por tantos años sufrimos, además de agregar otras funcionalidades que tanto gustaron como animaciones. Escribir jQuery es mucho más fácil porque resuelve las inconsistencias del lenguaje JavaScript entre browsers, pero actualmente eso está casi superado. Ya VueJS se enfoca en construir interfaces que reaccionen a medida que cambian los datos. Si vas a hacer un landing page que tenga sólo contenido, no es necesario VueJS. Si tus datos están en una API y necesitas rescatarla dinámicamente y después enviar datos devuelta al endpoint, VueJS es tu opción.

¿VueJS v/s Angular v/s React v/s cualquier otro?

No entraré en esa discusión, hay montones de artículos que lo discuten, cada uno con su punto de vista. Si quieres lee el mío escrito a mediados de este año.

Ya, muchas palabras poco código. Entremos de lleno en esto. Hay básicamente 2 maneras de usar VueJS: embebiendo la librería en una página HTML a través de <script> o usando WebPack. Por simplicidad, los ejemplos que entregaré en este artículo utilizarán la primera opción.

El inicio

Este es el Hola Mundo que verás en todos los ejemplos de VueJS:

See the Pen Vue para tod@s 01 by Octuweb (@octuweb) on CodePen.0

Revisemos el código:

<div id="app">
    <input type="text" v-model="textoCualquiera">
    {{ textoCualquiera }}
</div>

Creamos un <div id=”app”> para luego inicializarlo con JavaScript. Dentro de #app todo será reconocido por VueJS. Creamos un <input> con una directiva propia: v-model. Este v-model representa qué dato estará linkeado a su contenido. Al lado usamos el mismo v-model con esos brackets {{ textoCualquiera }} de esta manera es como renderizamos un dato definido en VueJS con HTML.

new Vue({
  el: '#app',
  data: {
    textoCualquiera: 'Soy un texto'
  }
})

Inicializamos VueJS y le decimos dónde en el HTML trabajará (#app). Luego creamos un dato (que puede ser String, Boolean, Number, Array u Object) en este caso es un String con contenido pre-definido. Ese dato está linkeado con el <input> por el v-model y a medida que cambiamos el texto en el campo el mismo dato en el HTML {{ textoCualquiera }} reaccionará en tiempo real.

Un poco más…

En el siguiente ejemplo, tendremos un Array con tipos de cerveza (soy amante de la cerveza 🤤) y las mostraremos en una lista haciendo un for (bucle):

See the Pen Vue para tod@s 02 by Octuweb (@octuweb) on CodePen.0

<div id="app">
    <h2>Tipos de cervezas:</h2>
    <ul>
      <li v-for="cerveza in tiposCervezas" :key="cerveza.id">{{ cerveza }}</li>
    </ul>
</div>

Obviando el título <h2> (el que podría ser dinámico, definido en data {{ titulo }} pero como no es reactivo para qué, si no va a cambiar), tenemos una lista desordenada <ul> con un <li> donde definimos el loop: v-for. El Array es tiposCervezas y cada elemento del Array será cerveza (pudo haber sido item, element, lo que sea). VueJS necesita un identificador único para iterar por lo que se define con el atributo dinámico :key un id del elemento del Array, en este caso cerveza.id (sin esto el loop no funcionará). Luego dentro del <li> el nombre de cada cerveza; el loop está ya hecho así que iterará solito.

new Vue({
  el: '#app',
  data: {
    tiposCervezas: [
      'Pale Ale',
      'Bock',
      'Porter',
      'IPA',
      'Trippel',
      'Lager'
    ]
  }
})

Sin novedades, el data tiposCervezas es un Array con varios tipos de cerveza.

Otro poquitito más…

VueJS es JavaScript, por ende puedes utilizar funciones y métodos propios de JS con VueJS. Pongamos en el título el total de cervezas que contiene el Array tiposCervezas con length:

See the Pen Vue para tod@s 03 by Octuweb (@octuweb) on CodePen.0

<div id="app">
    <h2>{{ tiposCervezas.length }} tipos de cervezas:</h2>
    <ul>
      <li v-for="cerveza in tiposCervezas" :key="cerveza.id">{{ cerveza }}</li>
    </ul>
  </div>

Simple, ¿no?

Show me the data!

Usemos una API de cervezas para poblar dinámicamente el listado de tipos de cervezas. Como VueJS se encarga sólo de la vista y de la reactividad de los datos, usaremos una librería externa para darle al endpoint y recibir los datos. La librería se llama Axios y es la recomendada por los mismos colaboradores de VueJS (podría usar fetch() que es nativo pero ya estoy muy acostumbrado a Axios):

See the Pen Vue para tod@s 04 by Octuweb (@octuweb) on CodePen.0

La API es un simple json que hospedé en GitHub, con los mismos datos anteriores pero cada uno en objetos:

{
  "cervezas": [
    {
      "id": 1,
      "nombre": "Pale Ale"
    },
    {
      "id": 2,
      "nombre": "Bock"
    },
    {
      "id": 3,
      "nombre": "Porter"
    },
    {
      "id": 4,
      "nombre": "IPA"
    },
    {
      "id": 5,
      "nombre": "Trippel"
    },
    {
      "id": 6,
      "nombre": "Lager"
    }
  ]
}

El HTML lo modifiqué un poco debido a ese nuevo formato; el nombre de la cerveza ahora tiene un key "nombre":

<div id="app">
    <h2>{{ tiposCervezas.length }} tipos de cervezas:</h2>
    <ul>
      <li v-for="cerveza in tiposCervezas" :key="cerveza.id">{{ cerveza.nombre }}</li>
    </ul>
</div>

Cargué la librería axios.min.js linkeado en el <script> y se crea un nuevo método traeCervezas() que obtiene esa data y la inyecta al mismo Array anterior tiposCervezas el que ahora está vacío; no tienes que hacer nada más, VueJS hará el data-binding y mutará la data en el HTML:

new Vue({
  el: '#app',
  data: {
    tiposCervezas: []
  },
  methods: {
    traeCervezas: function () {
     axios.get('https://my-json-server.typicode.com/juanbrujo/octuweb2018-demo/cervezas')
      .then(response => {
        this.tiposCervezas = response.data // inyectamos los datos en nuestro Array
      })
      .catch((error) => {
        console.error(error)
      });
    }
  },
  created: function () {
    this.traeCervezas() // inicializa
  }
})

El método traeCervezas() puede ser invocado al inicializar la app, mediante la instancia created(), o manualmente por ejemplo mediante el evento click de un botón, como en el siguiente ejemplo:

See the Pen Vue para tod@s 05 by Octuweb (@octuweb) on CodePen.0

HTML:

<div id="app">
    <h2>{{ tiposCervezas.length }} tipos de cervezas:</h2>
    <button @click="traeCervezas()">traeCervezas</button>
    <ul>
      <li v-for="cerveza in tiposCervezas" :key="cerveza.id">{{ cerveza.nombre }}</li>
    </ul>
</div>

JS:

new Vue({
  el: '#app',
  data: {
    tiposCervezas: []
  },
  methods: {
    traeCervezas: function () {
      axios.get('https://my-json-server.typicode.com/juanbrujo/octuweb2018-demo/cervezas')
      .then(response => {
        this.tiposCervezas = response.data
      })
      .catch((error) => {
        console.error(error)
      });
    }
  }
})

¿Y si lo hacemos bonito?

El creador de VueJS, Evan You, es diseñador de profesión y su buen gusto está siempre incorporado en esta librería. Un ejemplo es incorporar transiciones y animaciones por defecto, las que a través de la etiqueta <transition> permite con sólo CSS manejar los estados.

Agregaremos un nuevo dato: dataStatus que será un Boolean que cambiará a true apenas la API nos retorne las cervezas. Con esa condición v-if <transition> actuará:

See the Pen Vue para tod@s 06 by Octuweb (@octuweb) on CodePen.0

HTML:

<div id="app">
    <button @click="traeCervezas()">traeCervezas</button>
    <transition name="fade">
      <h2 v-if="dataStatus">{{ tiposCervezas.length }} tipos de cervezas:</h2>
    </transition>
    <transition-group name="fade" tag="ul">
      <li v-for="cerveza in tiposCervezas" :key="cerveza.id">{{ cerveza.nombre }}</li>
    </transition-group>
  </div>

CSS:

.fade-enter-active,
.fade-leave-active {
  transition: opacity .5s;
}
.fade-enter,
.fade-leave-to {
  opacity: 0;
}

JS:

new Vue({
  el: '#app',
  data: {
    tiposCervezas: [],
    dataStatus: false
  },
  methods: {
    traeCervezas: function () {
      axios.get('https://my-json-server.typicode.com/juanbrujo/octuweb2018-demo/cervezas')
      .then(response => {
        this.tiposCervezas = response.data
        this.dataStatus = true
      })
      .catch((error) => {
        console.error(error)
      });
    }
  }
})

Esto es sólo una pincelada de lo simple y de algo que VueJS permite; te invito a revisar su completísima documentación y si te gustó, te recomiendo tomar un curso práctico en Udemy u otra plataforma de e-learning, no te arrepentirás de lo mucho que puedes lograr con VueJS.

Jorge Epuñan

FrontEnd & UX & UI & autor y pensador; PhD en nada. Webdev por convicción en trabajar en lo que me apasiona. Desde hace 14 años aprendiendo y compartiendo mis perspectivas y conocimientos en desarrollo web en CSSLab.