Vue

De Manuais Informática - IES San Clemente.
Ir a la navegación Ir a la búsqueda

Vue.js es, en palabras de Evan You, su creador, un framework progresivo para crear interfaces de usuario. Vue se basa en una implementación muy ligera del patrón view-model que nos ayudará a relacionar nuestra capa de presentación con nuestra capa de negocio de forma sencilla y eficiente. A lo que se refiere You con ‘progresivo’, es a que es muy fácil añadir Vue.js a cualquier proyecto ya existente y poder aprovechar su funcionalidad casi sin complicaciones. Por el contrario, otros frameworks como Angular son mucho más orientados a comenzar proyectos desde cero, y con una arquitectura predeterminada que viene dirigida por el framework.

Vue comenzó originariamente como un proyecto que aspiraba a reproducir un conjunto mínimo de funcionalidades de Angular, pero sin tener que amoldarse a su arquitectura. Así, You, ingeniero de Google, comenzó a trabajar en Vue en 2013 y lo publicó en github en febrero de 2014. Actualmente Vue ha tenido un gran impacto y hay varias compañías de renombre que utilizan Vue en su front-end, como Gitlab, Alibaba o Nintendo.

Así, Vue.js se caracteriza por ser uno de los frameworks javaScript de mayor rendimiento, gracias a una implementación muy ligera del llamado virtual DOM.

Introducción al virtual DOM

Como sabemos, el DOM es una estructura en forma de árbol que se crea una vez que el navegador parsea una archivo HTML, contiene todos los elementos que deben ser renderizados en la página. Esto puede funcionar bien cuando se trata de una aplicación pequeña, pero empieza a volverse costoso cuando hay que encontrar un elemento en particular en un árbol que contenga cientos de nodos de una aplicación más grande. Para solucionar esto VUE, y otros frameworks, implementan un DOM virtual. El DOM virtual es una representación del DOM real en forma de objeto JS. Se utiliza con el objetivo de minimizar las interacciones con el DOM real.

Ventajas y desventajas del DOM virtual

Ventajas:
  • Te permite controlar cuando se actualiza el DOM real, si un elemento se modifica repetidas veces podemos hacer que se renderize solo su última modificación.
  • Es mucho menos costoso modificar una propiedad de un objeto JS que un elemento de un árbol, por lo que una aplicación web con DOM virtual será mucho más eficiente.
  • Sólo se vuelven a renderizar los elementos que hayan sufrido algún cambio, por ejemplo, si queremos cambiar de una página a otra sólo se volverán a renderizar los elementos que tengan alguna diferencia con el de la página anterior.
Desventajas:
  • Consume mas recursos, ya que necesita tener una copia del DOM cargada en memoria mientras siga funcionando la aplicación.
  • En un programa pequeño y con cambios pocos frecuentes en sus elementos el DOM virtual puede hacer que la aplicación funcione más lenta que con el DOM real, ya que agrega lógica a cada actualización.

Comenzar a trabajar con Vue.js

Vue.js tiene una documentación muy cuidada que nos permite ir aprendiendo desde cero cómo utilizar este framework de JavaScript.

El modo más sencillo de comenzar a utilizarlo es enlazar en nuestro proyecto el CDN de Vue.js. Para empezar a programar se enlazará la versión de desarrollo:

<!-- versión de desarrollo, incluye advertencias de ayuda en la consola -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

Ejemplos de introducción a Vue.js

Cambio dinámico

Vue nos permite de un modo dinámico cambiar el contenido de elementos de la web

  • HTML
<body>

    <div id="app">
      <!-- Propiedad para sustituir desde JavaScript -->
      {{ mensaje }} 
    </div>

    <!-- versión de desarrollo, incluye advertencias de ayuda en la consola -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <script src="scripts.js"></script>

</body>
  • JavaScript
// Archivo : "scripts.js"

// Creamos una instancia de objeto Vue
var app = new Vue({

    // Con 'el' proporcionamos a la instancia Vue un elemento DOM existente para montarla
    //puede ser un selector CSS o un elemento HTML
    //Vue convertirá recursivamente sus propiedades en getters/setters para hacerlas "reactivas"
    el: '#app',

    // Con 'data' definimos el objeto que guardará todos los datos
    //con los que trabajará la instancia Vue 
    data: {
        mensaje: 'Hola Vue!'
    }
})

Unión de caja de texto con otro elemento

También podemos realizar una ‘unión’ entre una caja de texto y cualquier otro elemento empleando la directiva v-model

  • HTML
<body>

    <div id="app">
        <h1>Saludo: {{ mensaje }}</h1>
        <input type="text" v-model='mensaje' />
    </div>

</body>
  • JavaScript
var app = new Vue({

    el: '#app',
    data: {
        mensaje: 'Hola Vue!'
    }
})

Aplicar condiciones

Con la directiva v-if podemos mostrar u ocultar elementos al cumplirse una condición:

  • HTML
<body>

    <div id="app">
        <!-- La directiva v-if se usa para representar condicionalmente un bloque. -->
        <span v-if="ok">Ahora me ves!!</span>
    </div>

</body>
  • JavaScript
var app = new Vue({
    el: '#app',
    data: {
        ok: true
    }
});


Un ejemplo más elaborado con v-if es el siguiente:

  • HTML
<body>

    <div id="app">
        <p v-if="hora < 12">Buenos días!</p>
        <p v-if="hora >=12 && hora < 20">Buenas tardes!</p>
        <p v-if="hora >= 20">Buenas noches!</p>
    </div>

</body>
  • JavaScript
var app = new Vue ({
    el: '#app',
    data: {
        hora: new Date().getHours()
    }
});


Y otro ejemplo donde, además, se utiliza la función setInterval de JavaScript, puede ser el siguiente:

  • HTML
<body>

    <div id="app">
        <p v-if="num < 12">Menor de 12</p>
        <p v-if="num >=12 && num < 20">Entre 12 y 20</p>
        <p v-if="num >= 20">Mayor de 20</p>
    </div>

</body>
  • JavaScript
var app = new Vue({
	el: "#app",
	data: {
		num: 0
	},
	methods: { //Definimos los métodos de nuestra instancia Vue
		testFunction() {
			//Utilizar function tipo "arrow" para acceder a las variables definidas en 'data'
			setInterval(() => { 
				this.num++;
				console.log(this.num);
			}, 1000);
		}
	},
	mounted() { //Se invoca después de que se ha montado la instancia
		this.testFunction();
	}
});

Definir el momento en el que se invoca un método

Vue.js nos permitirá definir acciones anteriores y posteriores a la transición desde o hacia cada estado interno del componente. Los métodos en cuestión para implementar estas acciones son:

  • beforeCreate : evento lanzado antes de tener el componente cargado, implica no poder acceder al componente a nivel de DOM.
  • created : evento donde se verifica si el componente tiene plantilla, entonces se compila y se observan las propiedades computads, data, métodos y eventos. Pero no podemos acceder al $el.
  • beforeMount : evento que ocurre antes de representar el commponente.
  • mounted : evento que implica que el componente está cargado por completo, se añade al DOM, quedando el componente accesible a través de $el.
  • beforeUpdate : evento que se ejecuta cuando el valor del data del componente cambia.
  • updated : evento invocado tras finalizar la modificación de valor del data.
  • beforeDestroy : evento que elimina eventos que estuvieran activos en el componente, antes de eliminar la instacia.
  • destroyed : evento lanzado tras desacoplar el componente.

v-if frente a v-show

Si v-if tiene un valor 'falsy', es decir, si es: false, undefined, null, 0, "" o NaN, el elemento asociado NO aparecerá en el DOM. Si, por ejemplo, tenemos esta plantilla:

<div v-if=”true”>Primero</div>
<div v-if=”false”>Segundo</div>

La salida será:

<div>Primero</div>

El funcionamiento de v-show es similar, pero distinto, pues utiliza CSS para mostrar u ocultar los elementos asociados. Si tenemos esta plantilla:

<div v-show=”true”>Primero</div>
<div v-show=”false”>Segundo</div>

La salida será:

<div>Primero</div>
<div style=”display: none>Segundo</div>

Saber que v-show tiene menor coste de procesamiento que v-if. Además, si el elemento contiene alguna imagen, entonces ocultar el contenedor solo con CSS permite que el navegador descargue la imagen antes de que se muestre, lo que significa que se puede mostrar tan pronto como v-show se ponga en true. Utilizando v-if, no comenzaría a descargarse la imagen hasta que se necesitase mostrar.

Bucles con v-for

Otra directiva interesante es v-for, que nos permite realizar un bucle a través de un objeto o un array.

  • HTML
<div id="app">
  <ol>
  <!-- Directiva empleada para representar una lista de elementos basada en un array. -->
    <li v-for="todo in todos">
      {{ todo.text }} <!-- Array de objetos clave:valor __ objeto.clave = valor -->
    </li>
  </ol>
</div>
  • JavaScript
  var app = new Vue({
    el: "#app",
    data: {
      todos: [
        //Array sobre el que vamos a iterar
        //Se trata de un array de objetos (clave:valor)
        { text: "Learn JavaScript" },
        { text: "Learn Vue" },
        { text: "Build something awesome" },
      ],
    }
  });

Y, si queremos hacer un simple contador, lo podemos hacer del siguiente modo:

  • HTML
<div id="app">
  <ul>
    <li v-for="n in 10">{{ n }}</li>
  </ul>
</div>
  • JavaScript
var app = new Vue({
	el: "#app",
});

Enlazar atributos y propiedades de elementos DOM

Podemos enlazar también atributos o propiedades de elementos del DOM:

  • HTML
<div id="app">
  <!-- v-bind enlaza dinámicamente uno o más atributos o componentes a una expresión -->
  <span v-bind:title="mensaje"> <!-- El atributo 'title' muestra una 'tooltip' -->
    Al poner el puntero sobre mí. <br>
    Sale un mensaje (tooltip text)
  </span>
</div>
  • JavaScript
var app = new Vue({
  el: '#app',
  data: {
    mensaje: 'Fecha actual: ' + new Date().toLocaleString()
  }
});

Podemos configurar también alguna propiedad de los elementos DOM. Veamos un ejemplo con un botón:

  • HTML
<div id="app">
  <button v-bind:type="buttonType">Botón de test</button>
</div>
  • JavaScript
var app = new Vue({
  el: '#app',
  data: {
   buttonType: 'submit'
  }
});
//Salida : <button type="submit">Botón de test</button>

Que funcionaría de igual modo con las propiedades disabled y checked.

También saber que, normalmente, se utiliza la versión corta a la hora de utilizar v-bind.

  <button :type="buttonType">Botón de test</button>

Enlace de datos bidireccional

Veamos un ejemplo donde se actualizan los datos de la web empleando botones "radio".

  • HTML
<div id="app">
			<label><input type="radio" v-model="value" value="uno">Uno</label>
			<label><input type="radio" v-model="value" value="dos">Dos</label>
			<label><input type="radio" v-model="value" value="tres">Tres</label>
			<br>
			<p>El valor es : {{ value }}</p>
		</div>
  • JavaScript
var app = new Vue({
	el: '#app',
	data: {
	  value: 'uno'
	}
});

Capturar eventos

Para capturar eventos podemos utilizar la directiva v-on para escuchar eventos DOM y ejecutar código JavaScript cuando se activan.

  • HTML
<div id="app">
  <p>{{ message }}</p>
  <!-- Capturar un evento… en este caso 'click' -- Llamamos a la función 'reverseMessage' --> 
  <button v-on:click="reverseMessage">Mensaje Inverso</button>
</div>
  • JavaScript
  var app = new Vue({
    el: "#app",
    data: {
      message: "Hola Vue.js!",
    },
    methods: {
      reverseMessage: function () {
        // 'this' hace referencia al 'div' donde está el botón
        this.message = this.message.split("").reverse().join("");
      }
    }
  });

Métodos

Vue nos permite crear funciones para no tener que repetir código y utilizar éstas como métodos. Veamos un ejemplo:

  • HTML
<div id="app">
 <input type="text" v-on:keyup="estadoFromId(estadoId)" v-model="estadoId" />
 <p>Tu estado actual es: {{ estado }}</p>
</div>
  • JavaScript
  var app = new Vue({
    el: '#app',
    data: {
      estadoId: 2,
      estado: ''
    },
    created: function() {
      this.estado = this.estadoFromId(this.estadoId);
    },
    methods: {
      estadoFromId(id) {
        //console.log(id);
        const e = ({
          0: 'Durmiendo',
          1: 'Comiendo',
          2: 'Aprendiendo Vue'
        })[id];
        this.estado = e || 'Estado desconocido ' + id;
      }
    },
 });

Veamos otro ejemplo interesante donde un método devuelve un array con los números positivos existentes en otro más amplio que se le pasa como parámetro. Con ese método se crea una lista:

  • HTML
<div id="app">
  <ul>
    <li v-for="numero in filtraPositivos(numeros)">{{ numero }}</li>
  </ul>
</div>
  • JavaScript
new Vue({
  el: "#app",
  data: {
    numeros: [-5, 0, 2, -1, 1, 0.5],
  },
  methods: {
    filtraPositivos(numeros) {
      return numeros.filter((numero) => numero >= 0);
    }
  }
});

this

Como vimos antes, en un método, this se refiere al componente al que está asociado el método. Se puede acceder también a las propiedades y a otros métodos también. Veamos un ejemplo donde se demuestra esto:

  • HTML
  <div id="app">
    <ul>
      <p>
        La suma de los números positivos de la lista: {{numeros.join(', ')}} -> Es: {{calculaSumaNumPos()}}
      </p>
    </ul>
</div>
  • JavaScript
new Vue({
  el: "#app",
  data: {
    numeros: [-5, 0, 2, -1, 1, 0.5],
  },
  methods: {
    filtraPositivos() {
      return this.numeros.filter((numero) => numero >= 0);
    },
    calculaSumaNumPos() {
      return this.filtraPositivos().reduce((sum, val) => sum + val);
    },
  },
});

Watchers

Si bien las propiedades computadas son más apropiadas en la mayoría de los casos, hay ocasiones en que es necesario un observador personalizado. Es por eso que Vue proporciona una forma más genérica de reaccionar a los cambios de datos a través de la opción watch. Esto es más útil cuando desea realizar operaciones asíncronas o costosas en respuesta al cambio de datos.

  • HTML
<div id="app">
  <input type="text" v-model="inputValue" />
  <br />
  <p>Cinco segundos después, en la entrada: {{ oldInputValue }}</p>
</div>
  • JavaScript
new Vue({
  el: "#app",
  data: {
    inputValue: "",
    oldInputValue: "",
  },
  watch: {
    inputValue() {
      const newValue = this.inputValue;
      setTimeout(() => {
        this.oldInputValue = newValue;
      }, 5000);
    },
  },
});

Aplicaciones sencillas

Libreta de pagos pendientes con Vue.js

Video fuente
<!-- Web inicio -->