En esta lección vamos a trabajar en un componente un poco más complicado, será un componente para representar una tarea (es decir una fila o registro o «modelo»). Este componente agrupará las propiedades y acciones relacionadas con la tarea y nos permitiría limpiar aún más el código de nuestra plantilla principal.
Notas
Debido a que el código HTML de la plantilla de nuestra lista de tareas es mucho más complejo no sería lo más adecuado colocar la plantilla en línea. Por está razon creamos otra etiqueta <script> donde colocamos toda nuestra plantilla. A esta etiqueta debemos añadirle el atributo «type» con el valor «text/x-template», esto es para indicarle al navegador que el código dentro de la etiqueta script no es JavaScript. También le asignamos un id para poder hacer referencia a la plantilla desde nuestro código de Vue.js:
<script type="text/x-template" id="task-template"> <!-- Aquí va el código de nuestra plantilla --> </script>
Dentro del componente app-task
que creamos para nuestra lista de tareas debemos hacer referencia a nuestra plantilla. Además definimos las propiedades de nuestro componente, en este caso la tarea (task
) y el indice de la tarea (index
):
Vue.component('app-task', { template: '#task-template', props: ['task', 'index'] });
En nuestra plantilla principal index.html hacemos referencia a nuestro componente. Es importante tener en cuenta que Vue.js no va a pasar las propiedades del componente automáticamente, por lo que debemos hacerlo de forma explícita indicando nuestras propiedades (task
y index
) mediante la directiva v-bind
:
... <ul class="list-group tasks"> <li is="app-task" v-for="(task, index) in tasks" :task="task" :index="index"></li> </ul>
Debido a que nuestro componente se encuentra dentro de una etiqueta <ul>
, para evitar problemas con el navegador debemos hacer uso de la etiqueta <li>
e indicarle a Vue mediante el atributo especial is
que este «list item (li)» va a ser en realidad el componente app-task
.
Aprende más sobre el atributo especial is de Vue.js.
Más adelante aprenderemos cómo eliminar esta restricción para poder usar directamente <app-task>
dentro de un <ul>
.
Anteriormente la directiva v-for
se encontraba directamente en la plantilla de nuestra tarea. Como nuestro componente no va a hacer referencia a todas las tareas si no a una sola tarea puntual, eliminamos la directiva de la etiqueta <li>
de la plantilla y la agregamos en su lugar en app-task
. Al hacer esto le indicamos a Vue que por cada registro o tarea se imprima un nuevo componente app-task
para representar a dicho registro.
Si estás utilizando la extensión de Vue.js para Chrome, podrás ver desde la pestaña Vue del inspector los diferentes componentes de tu aplicación y sus propiedades entre otros detalles.
Debido a que cada componente es básicamente un objeto VM independiente, debemos pasar el método toggleStatus
(la función que nos permite cambiar el estado de nuestra tarea) que se encuentra en el objeto VM principal a nuestro componente app-task
.
Vue.component('app-task', { template: '#task-template', props: ['task', 'index'], methods: { toggleStatus: function(task) { task.pending = !task.pending; }, } });
Como nuestro componente representa una tarea individual que pasamos como una propiedad, ya no necesitamos definir el parámetro task
a toggleStatus
, si no que podemos hacer referencia a la tarea directamente con this
:
... methods: { toggleStatus: function() { this.task.pending = !this.task.pending; }, }
De igual forma cuando llamamos a toggleStatus
desde nuestro HTML no necesitamos pasar la tarea como argumento:
<!-- Antes --> <a @click="toggleStatus(task)">…</a> <!-- Después --> <a @click="toggleStatus">...</a>
Este proceso lo realizamos con todos nuestros otros métodos (editTask
, updateTask
, discardTask
, deleteTask
), y de nuevo es importante destacar que no necesitamos pasar ni la tarea (task
) o el indice (index
) a nuestros métodos ya que podemos hacer referencia a estos con el uso de this
.
Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.
Lección anterior Creación y uso de tu primer componente con Vue.js 2 Lección siguiente Separación de datos entre el modelo y la vista en Vue.js 2