Primeros pasos con Vue.js

Vuejs es una libreria de JavaScript centrada en la creación de interfaces de usuarios, es un nuevo framework que cada vez gana mas popularidad debido a su fácil aprendizaje, su rendimiento y su usabilidad y adaptación.
Entre las caracteristicas principales de Vuejs encontramos que es un Framework reactivo que implementa “Two way data-binding” en español “Enlace de datos en dos direcciones (vista y modelo), y esto lo hace de una manera muy eficiente y rápida.

– Vuejs esta mas enfocado hacia la vista y se puede implementar en cualquier HTML, sin que requiera cambios drásticos en el marcado.
– Vuejs es una librería Model View * es decir: Modelo, Vista, Lo que sea, por ende podemos utilizar vistas que estén atadas a los modelos, sin importar que tenga como controlador.
– Vuejs esta orientaddo a componentes reutilizables, podemos escribir componentes y utilizarlos en la app cuantas veces sea necesario.

Podemos decir que Vuejs + Herramientas + librerias = Single Page Aplication

Vue.js tiene similitudes con React.js veamos cuales son:

  • Ambos utilizan un DOM (Document Object Model) virtual, de manera que cuando se genera un cambio, vuejs sabe que elemento modificar del DOM.
  • En ambas librerías podemos escribir componentes re utilizables
  • Libreria core solo para la UI: En caso de querer manejar el estado de nuestra app de una manera mas global y compleja. Para reac tenemos que usar Redux y en el caso de Vue tenemos que usar una libreria llamada Vuex
  • En Reacjs el HTML lo colocamos en el metodo render y es lo que se termina dibujando en la SPA (Single Page Aplication), en Vuejs el HTML lo colocamos dentro de una etiqueta <template> y dentro de esta etiqueta tenemos varias directivas las cuales deciden si aparece o no aparece el elemento.

 

 

Para incluir la librería de Vuejs simplemente copiamos el script que nos brinda su pagina oficial  al final del <body>

<script src=”https://unpkg.com/vue”></script>

Luego de incluir la librería podemos incluir un script y en el empezar a copiar la lógica de nuestra app.

<script>
let app = new Vue({

el: ‘#app’,
data: {

nombre: ‘David’,
url: ‘https//davidrojas.com.ve’,
pagina: ‘DavidRojas – Blog’,
titulo: ‘esto es un titulo de prueba’

},
filters: {

upper: function (str) {

return str.charAt(0).toUpperCase() + str.slice(1);

}

}

})
</script>

En este ejemplo podemos ver lo siguiente:
let app es nuestro componente padre, este componente padre tiene un objeto Vue el cual tiene un elemento  “#app” –>  el: ‘#app’ el cual va a ser el id de nuestro <div id=”app></div> este div va a recibir por todas las variables que se definan en el objeto Vue, en este caso definimos las variables:
nombre, url, pagina y titulo.

Para imprimir o mostrar esas variables en el div, lo hacemos en medio de dos corchetes {{ variable }} de esta manera Vue lo va a entender y va a mostrar el contenido de la variable.

<div id=”app“>
<h1> Hola {{ nombre }} </h1>
Ir a <a v-bind:href=”url” target=”_blank”> {{ pagina }} </a>
<h3> {{ titulo | upper }} </h3>
</div>

Como podemos ver, las variables se copian dentro de los corchetes para que Vuejs las pueda interpretar, también visualizamos que en el caso de la variable url por estar dentro de un valor de HTML, no lleva corchetes pero si debemos colocarle  v-bind: antes del atributo y le pasamos la variable al contenido de ese atributo, en este caso la variable url.
También podemos ver que en el caso de la etiqueta <h3> que a parte de la variable titulo tenemos un símbolo ” | ” este símbolo se utiliza para agregar filtros, estos filtros, en este caso nuestro filtro se llama upper  y este filtro lo definimos dentro del objeto Vue, después de data, dentro de un JSON llamado filters
Para este ejemplo el filtro upper lo que tenemos es una función la cual nos va a colocar el primer carácter de la variable titulo, en mayúsculas, pero en esta función podemos colocar lo que nosotros queramos, bien sea un alert, otra función mas compleja, etc.

Una variable puede tener varios filtros, ejemplo {{ variable | filtro1 | filtro2 | filtro3 }}

 

Mostrar y ocultar elementos

Para mostrar u ocultar elementos es necesario que usemos el atributo v-if=”id” este atributo va a funcionar como una condicional, la cual nos va a mostrar en pantalla el contenido si esa condicional es igual a true, en caso contrario, es decir en caso de que esa condicional sea igual a false nos va a ocultar el contenido.

Esta variable la vamos a definir en la data de nuestro objeto Vue.

Y el atributo v-if=”condicion” lo vamos a agregar en la etiqueta que queremos mostrar u ocultar.

En caso de querer ocultarlo, solamente debemos cambiar el booleano true por false 🙂

¿Pero que sucede si queremos ocultar o mostrar varios elementos?

Una posible solución es meter todos los elementos que queremos mostrar u ocultar dentro de un <div> y a ese <div> colocarle el atributo v-if


Sin embargo no es la mejor solución, ya que tendriamos un <div> innecesario y esto afectaría el HTML que se renderiza o se dibuja en la pantalla del usuario.

Para este tipo de casos Vuejs nos ofrece las etiquetas <template>

Las ventajas de usar la etiqueta <template> es que esta etiqueta no se va a terminar dibujando en el HTML final.

Mostrar u ocultar elementos con v-show

Este atributo también se utiliza para mostrar información y a su vez ocultar otra, en resumen se puede decir que se tienen dos contenedores y si se muestra uno se oculta el otro.

Cabe resaltar que el v-show no funciona para las etiquetas <template> debido a que las etiquetas template no forman parte del HTML final, y
v-show tiene como funcionalidad agregar un display: block o inline-block a uno de los <div>  y al otro div agregarle un display: none.

Diferencias entre v-if y  v-show

v-if : Destruye el contenido, es decir: Lo elimina.

v-show : Muestra y oculta contenido mediante display none y display block.

También es importante tener en cuenta que para el navegador es mas fácil v-show, es decir que para un render inicial conviene usar v-if y si es algo que se tiene que mostrar u ocultar dependiendo de las interacciones del usuario, conviene utilizar v-show 


Contador con Vuejs

En este ejemplo vamos a hacer un contador, de manera que le podamos sumar o restar a una variable, mediante dos botones (sumar y restar).

Para que se ejecute cierta lógica al hacer un click, debemos colocar v-on:click=”nombre del metodo, ese metodo lo vamos a declarar dentro del objeto Vue({ … }) en este objeto tenemos varios JSON como data, filters y en este caso tambien tenemos methods.

let app = new Vue({

el: ‘#app’,
data: {

nombre: ‘David’,
url: ‘https//davidrojas.com.ve’,
pagina: ‘DavidRojas – Blog’,
titulo: ‘esto es un titulo de prueba’,
contador: 0

},
filters: {

upper: function (str) {

return str.charAt(0).toUpperCase() + str.slice(1);

}

},

methods: {

sumar() {

this.contador++;

},

restar() {

this.contador–;

}

}

})

Tambien podemos resumir un poco el condigo, si queremos ahorrarnos el v-on: podemos sustituirlo por un @ ejemplo:

v-on:click=”sumar”
@click=”sumar”

Y a su vez podemos resumirlo un poco mas, colocando la funcion en el mismo atributo @click=”contador++ o en su defecto @click=”contador–” asi como se visualiza en la imagen


Manejo de formularios

Vamos a crear un formulario que nos permita mostrar el texto ingresado en el, en otra etiqueta aparte…
Ejemplo: <input type=”text” placeholder=”Ingresa tu nombre”>  <h1> Aquí se va a mostrar el texto ingresado en el formulario </h1>

Adicional a eso, le vamos a colocar un filtro para que el texto ingresado en el formulario, lo convierta todo en mayúsculas.

Para que el texto que reciba el <input> se muestre en la etiqueta <h1> es necesario pasarle al input el atributo v-model,
v-model: En resumen se puede decir que es una directiva que se usa para crear enlaces de datos bidireccionales en los elementos input y textarea del formulario.

Es super importante saber que la variable que coloquemos en el atributo v-model, tambien debemos declararla en el objeto Vue, asi como se puede apreciar en la imagen..

Sin embargo en la imagen aun no hemos agregado el filtro para transformar el texto a mayúsculas, lo vamos a hacer mediante los filtros que ya mencionamos más arriba, quedando nuestro código así..

 

Formulario dinámico con checkboxs

En este ejemplo vamos a hacer un formulario -> <form> y para evitar que cuando hagamos click en el submit de ese formulario el navegador haga su tarea por defecto, a ese formulario le vamos a pasar el parametro v-on:submit.prevent. Recordemos que cuando se trata de un evento podemos resumirlo así @submit.prevent=”submit donde submit es un metodo el cual vamos a declarar en el objeto Vue, de la siguiente manera:

methods: {

submit: function () {

console.log(“Se ha ejecutado el metodo Submit 😀 “)

}

}

Ahora vamos a acceder a una lista de contenido que tengamos en ese formulario, esta va a ser una lista de checkboxs. Para ello debemos declarar en el objeto Vue, un array de ese contenido: nombre_del_array [] 
El checkbox en vez de tener el atributo name va a tener el atributo v-model y como parametro le vamos a pasar el nombre_del_array, quedando asi:  <input type=”checkbox” v-model=”nombre_del_array” />

Es importante recordar que debemos colocarle el v-on:submit.prevent=”nombre del metodo a la etiqueta form.

Y por ultimo en ese metodo vamos a definir una funcion por medio de la cual vamos a acceder a ese array que declaramos en el objeto Vue:

methods: {

submit: function () {

console.log(this.nombre_del_array)

}

}

Quedando nuestro código así:

Al correr el código en el navegador, podemos observar en el inspector de elementos, estamos haciendo un console.log al array, para este ejemplo vamos el array  es “usuarios” el cual nos va a mostrar los usuarios que seleccionamos.

El atributo Observer que se visualiza en el console.log lo agrega vuejs para poder hacer el bind entre los elementos del DOM y los de JavaScript.


Ciclos e interacciones con vuejs

Para este ejemplo vamos a listar nuevamente unos checkboxs de usuarios, pero esta vez lo vamos a listar de manera dinamica, gracais a vuejs.

Para ello en la data del objeto Vue, vamos a enviar los usuarios que existen mediante un array y a parte vamos a tener otro array para almacenar los usuarios seleccionados.

data: {

usuarios: [

{ nombre: ‘David’, value: ‘David’ },
{ nombre: ‘Jose’, value: ‘Jose’ },
{ nombre: ‘Juan’, value: ‘Juan’ },
{ nombre: ‘Miguel’, value: ‘Miguel’ }

],
usuariosSeleccionados: []

}
methods: {

submit () {

console.log(“this.usuariosSelccionados”)

}

}

Muy bien, ahora vamos a crear un <template> y vamos a hacer un checkbox y un label con un ciclo que nos permite hacer vuejs.
Vamos a hacer un ciclo con cada uno de los usuarios que le enviamos a la vista, para ello vamos a utilizar v-for.
v-for
cuenta con 2 parametros (una variable para ir iterando con los elementos que tenga el array y la otra variable es el array.
Quedando asi: v-for=”u in usuarios” donde u es la varaible que utilizamos para ir iterando con los elmentos del array y usuarios es el array que definimos en la data del objeto Vue.

v-bind es el atributo que usamos para bindear el valor con el usuario correspondiente.

v-model=”usuariosSeleccionados” es el array que se va a ir llenando a medida que vayamos seleccionando usuarios.

El elemento <template> como lo vimos más arriba, no va a existir en el DOM ya que el navegador no puede interpretar a un elemento <template>, sino que estos elementos lo vamos a utilizar dentro de vue para agrupar ciertos elementos que queremos que figuren juntos. 🙂


Componentes

Vamos a hacer el mismo código del ejemplo anterior un poco mas declarativo, para ello antes de declarar el objeto Vue (nuestro componente principal) vamos a crear un componente, de manera que cada vez que aparezca la etiqueta o el tag que le demos a ese componente, se muestre el código en pantalla.

Vue.component(‘usuario’, {

template: `——-`;

})

usuario: es el nombre de la etiqueta o tag.
El segundo parametro { template: “ } es un objeto d JS, y aquí vamos a indicar como queremos que ese componente se muestre en la pantalla.

Usamos `comillas invertidas` para poder hacer uso de los enter o saltos de lineas, sin afectar el código.
Dentro de esas comillas invertidas `<div> </div>` vamos a declarar una etiqueta div, la cual va a contener todo el código de nuestro componente, es decir el codigo que se va a dibujar en pantalla.. Porque hacemos esto? Ya que nuestro render consta de mas de un elemento, vuejs necesita interpretar un solo elemento padre, en este caso nuestro <div> que se va a encargar de cubrir el resto del código.
Ahora si, vamos a pasarle el input type=”checkbox” y el label a ese template, quedando asi:

Vue.component(‘usuario’, {

template: `

<input type=”checkbox” v-model=”usuariosSeleccionados” v-bind:id=”u.value” v-bind:value=”u.value” /> 
<label v-bind:for=”u.value“> {{ u.nombre }} </label> 

`;

})

Como podemos ver estamos utilizando variables de Vue que no le estamos pasando al componente ‘usuario’ como lo es:
– usuariosSeleccionados
– u.value
– u.nombre

Para indicar las propiedades que necesita ese componente, vamos a definir el atributo props: [] y ahi definimos las propiedades que el componente necesita para dibujarse…

Vue.component(‘usuario’, {

props: [ ‘u’, ‘usuariosSeleccionados’] ,

template: `

<input type=”checkbox” v-model=”usuariosSeleccionados” v-bind:id=”u.value” v-bind:value=”u.value” /> 
<label v-bind:for=”u.value”> {{ u.nombre }} </label> 

`;

})

Como pueden ver necesitamos de la variable u que es la del ciclo for, para poder iterar en los checkbox y tambien necesitamos del array usuariosSeleccionados ya que ahi se va a almacenar los usuarios que seleccionemos.

Ahora tenemos que pasarle los parametros indicados a la etiquetea <usuario> dentro del HTML.

<template v-for=”u in usuarios”>

<usuario v-bind:u=”u” v-bind:usuarios-seleccionados=”usuariosSeleccionados”> </usuario>

</template>

Como podemos ver la variable u es la misma que esta iterando en el for del template, y la variable usuarios-seleccionados es la misma que definimos en el atributo props del componente, sin embargo aqui se escribe usuarios-seleccionados ya que los atributos HTML no son sensitivos a mayusculas o minusculas..

El codigo debe quedarnos asi:

En este punto se nos dibuja el componente en pantalla, tal cual como lo queremos:

Pero sin embargo el componente no cumple con su función como debe ser, ya que al seleccionar los usuarios para enviarlos al array usuariosSeleccionados, nos genera un error…

Y esto se debe a un antipatron en Vue.js a continuación vamos a ver la explicación y la solución a este error…

Parent: Es el componente padre de nuestra aplicacion, es el objeto Vue.
Child: Es el componente del usuario

Desde el componente padre le estamos pasando propiedades al componente hijo ( usuario ), pero este componente hijo no debe modificar directamente sobre los atributos del padre.
Esta mal pasarle al hijo los usuariosSeleccionados para que el los modifique desde afuera…

La manera correcta es que el hijo emita eventos para que el padre responda ante esos eventos, dijimos que el componente ‘usuario’ tiene que emitir un evento cada vez que suceda algo, y el padre debe escuchar esos eventos.

Entonces cada vez que seleccionemos un usuario el componente ‘usuario’ va a emitir un evento diciendo si ese usuario fue checkeado o descheckeado, y el padre va a tener el registro de los usuariosSeleccionados.

Para ello vamos a quitar del props del componente usuario los usuariosSeleccionados, asi como tambien vamos a quitar en el input el v-model=”usuariosSeleccionados”…

Vue.component(‘usuario’, {

props: [ ‘u’, ‘usuariosSeleccionados’] ,

template: `

<input type=”checkbox” v-model=”usuariosSeleccionados” v-bind:id=”u.value” v-bind:value=”u.value” /> 
<label v-bind:for=”u.value”> {{ u.nombre }} </label> 

`;

})

También debemos quitar el atributo dentro de la etiqueta <usuario> en el HTML…

<template v-for=”u in usuarios”>

<usuario v-bind:u=”u” v-bind:usuarios-seleccionados=”usuariosSeleccionados”> </usuario>

</template>

Como debemos emitir un evento cada vez que se checkee un usuario, vamos a hacer un bind del evento change en el input checkbox.
@change=”onchange” 
change: Es el evento
onchange: Nombre del evento

Quedando nuestro input así:
<input type=”checkbox” v-bind:id=”u.value” v-bind:value=”u.value” @change=”onchange” />

Este evento onchange debemos definirlo dentro del JSON methods el cual va en el componente hijo..

Vue.component(‘usuario’, {

props: [ ‘u’] ,
methods: {

onchange: function (ev) {

this.$emit(‘checked’, this.u.value, ev.target.checked)

}

}

template: `

<input type=”checkbox” v-bind:id=”u.value” v-bind:value=”u.value” /> 
<label v-bind:for=”u.value”> {{ u.nombre }} </label> 

`;

})

La funcion onchange va a recibir por parámetro un evento –> (ev) el evento se dispara cuando se cambie el valor del checkbox, lo que nos interesa saber es si el checkbox esta checkeado o no esta checkeado.
Para emitir un evento debemos llamar al método this.$emit() este metodo recibe varios parámetros:
– El primer parámetro es el nombre del evento que queremos emitir, en este caso 
– El segundo parámetro es el usuario que se seleccionó
– Y el tercer parámetro es para indicar si el elemento fue checkeado o descheckeado, eso lo vamos a hacer accediendo a la variable del evento ev.target.checked y nos va a devolver TRUE o FALSE 

Ahora en el componente padre debemos estar escuchando cada vez que se dispare el evento…

Esto lo hacemos en la etiqueta usuario (en el HTML) :
<usuario :u=”u” v-on:checked=”selectUser”></usuario>

v-on –> Como cualquier otro evento
v-on:checked –>
Nombre del evento
v-on:checked=”selectUser” –> El valor del atributo, este va a ser el metodo que queremos llamar dentro de nuestro componente padre.

selectUser: Este metodo debempos definirlo en el JSON methods del componente padre… 

methods: {

submit () {

console.log(this.usuariosSeleccionados)

},
selectUser: function (us, checked) {

if (checked){

this.usuariosSeleccionados.push(us)

}
else {

let index = this.usuariosSeleccionados.indexOf(us)
this.usuariosSeleccionados.splice(index, 1)

}

}

}

La funcion va a recibir dos parametros:

us:  value del curso
checked: si fue checkeado o no

Si el usuario fue checkeado debemos agregarlo a la lista de usiariosSeleccionados, y si fue descheckeado debemos quitarlo de esa lista…
Para ello hacemos el condicional if 
Si (checked) es TRUE. le vamos a hacer un push a usuariosSeleccionados con el value del usuario (es decir: Con el usuario que se seleccionó)
else: Definimos cual es el indicie (let index) de ese usuario dentro de los usuariosSeleccionados –> this.usuariosSeleccionados.indexOf(us) 

Quitamos el indice del array: this.usuariosSeleccionados.splice(index, 1) El 1 significa que a partir de esa posicion del array se quita 1 del array.

Quedando nuestro código de esta manera: