Trabajando con plantillas VueJS

Posted by in Javascript y TypeScript

Seguimos con entradas de VueJS, y al igual que expliqué con TypeScript para el uso de plantillas usando Handlebars, es necesario comprender cómo son las plantillas en VueJS.

VueJS cuenta con un motor de plantillas muy similar a Handlebars, con lo que lo aprendido antes puede aplicarse de nuevo con VueJS.

Plantillas VueJS

Se trata de aplicar HTML con una sintaxis especial, al igual que se hizo con Handlebars, lo que permite introducir los datos en el HTML mediante el renderizado. Es similar a JSX de React, pero más liviano. Se realiza todo mediante un DOM virtual (al igual que React) lo que minimiza los tiempos de renderizado, enfatizando la rapidez del framework cuando hay cambios en los datos.

Antes de seguir, nos hacemos eco de v-cloak.

Que es v-cloak

Es una directiva que se puede incluir en el div contenedor de la aplicación (o componente) para evitar que se muestre la plantilla mientras tiene lugar el renderizado. Es justo el tiempo que tarda en ejecutarse el renderizado, en teoría es poco, pero así evitas que se vea {{ contenido }} antes de que muestre  Contenido.

Esta directiva requiere el apoyo de CSS adicional. Lo normal es incluir que se oculte todo lo que tenga v-cloak:

[v-cloak] {display: none}

Pero, se puede aprovechar esta circunstancia para incluir un mensaje de «Cargando …»

Te recomiendo que pases por aquí para que lo veas en acción, y uses el css:

[v-cloak] > * { display:none }
[v-cloak]::before { content: "Cargando …" }

Ejemplo de login

Para ilustrar lo que estamos consiguiendo, vamos con un ejemplo. Se trata de un pequeño formulario de acceso, y en caso de que se acceda, muestra otro contenido. Para darle un mejor aspecto, se hace uso de Bootstrap, por lo que verás algunas clases de este framework en la plantilla.

Se trata de poner en juego muchas de las cosas que hemos visto de vue, como propiedades computadas, funciones, … y las plantillas, que son otra de las claves de los objetos Vue.

El HTML es bastante simple, pues todo se desarrolla en Javascript:


<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Example templates</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" href="css/estilo.css">
</head>

<body>
<div id="app" v-cloak>

</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
<script src="src/login.js"></script>
</body>

</html>

Para el código en Javascript, lo primero es definir un modelo de datos, que será:

  • Un objeto user, que tiene una propiedad nombre y otra propiedad password
  • Un listado de errores
  • Logged para saber si está logueado o no

Vamos a definir una propiedad computada, que permita comprobar si el formulario que utilizamos está completo o no: is_form_empty.

Los métodos a definir son:

  • login, donde se verifica que hay algo en nombre y en clave, y si las credenciales son correctas
  • logout, que resetea los valores del modelo

Y solo queda la plantilla, que es el código HTML que va incluido en template, y será lo que se muestre.

El código completo es:


const app = new Vue({
el: '#app',
data: {
user: { name: null, password: null },
errors: [],
logged: false
},
computed: {
is_form_empty: function () {
return !(this.user.name && this.user.password);
}
},
methods: {
login: function () {
this.errors = [];
console.log('Logueando ...')
if (this.user.name.length < 6) {
this.errors.push('El nombre de usuario tiene que tener al menos 6 caracteres');
}

if (this.user.password.length < 6) {
this.errors.push('La contraseña tiene que tener al menos 6 caracteres');
}
if (!this.errors.length) {
if (this.user.name == "testing" && this.user.password == "manejando") {this.logged = true} else
{ this.errors.push('Usuario o clave incorrecta'); };
}

},
logout: function() {
this.errors = [];
this.user = { name: null, password: null };
this.logged = false;
console.log('Log out')
}
},
template: `
<div>
<h1 class="jumbotron">Bienvenido {{ user.name }}</h1>

<div class="login-errors-container container" v-if="errors.length !== 0">
<ul class="login-errors list-group">
<li v-for="error in errors" class="list-group-item list-group-item-danger"> {{ error }}</li>
</ul>
</div>

<form class="login container" v-on:submit.prevent="login" v-if="!logged">
<div class="login-field">
<label for="username" class="form-label">Nombre de usuario</label>
<input id="username" type="text" v-model="user.name" class="form-control"/>
</div>

<div class="login-field">
<label for="password" class="form-label">Contraseña</label>
<input id="password" type="password" v-model="user.password" class="form-control"/>
</div>

<div class="login-field">
<button type="submit" v-bind:disabled="is_form_empty" class="btn btn-primary">Entrar</button>
</div>
</form>


<div class="contenido container" v-if="logged">
<h2>Contenido</h2>
<button class="btn btn-default" @click="logout">Cerrar</button>
</div>
</div>
`
});

Revisando algunas cosas, puedes comprobar cómo usamos @click para lanzar evento del botón, o cómo enviamos el formulario a que se ejecute login desde v-on:submit.prevent

plantillas VueJS

plantillas VueJS

Sinceramente, muy poco código para cumplir el objetivo, lo que demuestra la potencia de VueJS.

En el siguiente paso, transformaremos todo lo realizado en un componente, listo para reutilizar.

Happy coding!