En la anterior entrada, vimos un ejemplo de cómo utilizar las plantillas en Vue, y ahora, ese mismo código, lo vamos a emplear en crear un componente en VueJS. La documentación oficial es bastante extensa y a su vez clara de cómo proceder, si bien, no es muy similar a lo ya trabajado.
Los componentes en VueJS
Los componentes permiten “aislar” partes de una aplicación para concentrarnos exclusivamente en lo que pasa dentro, despreocupándonos del resto de cosas. Se trata de instancias Vue reutilizables!
Si la instancia Vue necesita de un elemento “el” para desarrollarse, los componentes necesitan de template (aunque también puede hacer componentes que no necesiten plantilla, pero eso será tratado más adelante).
La creación de componentes
Solo hay que incrementar las opciones de la instancia Vue con:
Vue.component(‘nombre’, { })
El primer parámetro es el nombre del componente, lo que permite usarlo en HTML como <nombre></nombre>.
Mola, eh?
El segundo parámetro es un objeto, y será donde se incorpore la lógica del componente. Aunque muchas de las propiedades ya vistas son iguales a las que se usarán en los componentes, existen algunas diferencias. La principal: data es ahora una función!
Los componentes también permiten que se les transfiera información, mediante props que es a un array, o un objeto donde las claves definen las propiedades del modelo. La documentación oficial explica muy bien situaciones complejas para, por ejemplo, obligar a que una propiedad tenga dato, o bien incluir un dato predeterminado, que sea opcional, …. Todo, muy bien especificado dentro de un objeto!
Volvamos al ejemplo del Login
Para ver la potencia de los componentes, vamos a modificar el ejercicio anterior de Login, y transformarlo en un componente.
El código HTML permanece invariable, es decir, no tiene ninguna modificación (salvo llamar a un nuevo fichero Javascript).
El código del componente es, casi idéntico a lo que teníamos en el ejemplo de las plantillas, con excepción de la propiedad data, que ha cambiado a una función que devuelve un objeto. Antes teníamos:
data: {
user: { name: null, password: null },
errors: [],
logged: false
},
Y ahora tenemos:
data: function () {
return {
user: { name: null, password: null },
errors: [],
logged: false
}
}
Por lo demás, la propiedad template queda exáctamente igual, al igual que las propiedades computadas o las funciones.
Registramos el componente, que hemos llamado login:
Vue.component('login', { template: ` <div> <h1 class="jumbotron">Bienvenido {{ user.name }}</h1> <div class="login-errors-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 class="container">Entra con usuario 'testing' y clave 'manejando'</div> </div> `, 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') } }, data: function () { return { user: { name: null, password: null }, errors: [], logged: false } } })
Solo nos queda modificar la instancia Vue inicial, que queda tal que así:
const app = new Vue({ el: '#app', template: `<login></login>` });
En la template, hemos incluido el componente login creado.
Sencillo, eh? Pues a seguir aprendiendo!