Esta es una lección muy interesante e importante del curso de Vue.js 2, puesto que aprenderemos cómo separar y diferenciar datos de nuestro modelo de aquellos datos que únicamente forman parte de la interfaz de usuario o vista. Además aprenderemos cómo asociar propiedades adicionales al modelo de forma reactiva, definir y usar la propiedad data dentro de los componentes y mucho más:

Suscríbete a nuestro boletín

Te enviaremos publicaciones con consejos útiles y múltiples recursos para que sigas aprendiendo.

Notas

En nuestra aplicación las tareas están almacenadas dentro de un Array de objetos llamado tasks, acá almacenamos la descripción de nuestras tarea (description), el estado de la tarea (pending) y el estado de edición (editing).

tasks: [
    {
        description: 'Aprender Vue.js',
        pending: true,
        editing: false
    },
    ...
]

Sin embargo, al no formar parte del contenido de la tarea, la propiedad editing no debería estar dentro del objeto que contiene la tarea. Si estuvieramos trabajando con una API y retornando las tareas desde una base de datos (tarea que haremos a futuro) la propiedad editing no formaría parte de nuestras tareas.

Tenemos diferentes formas de solucionar esto, una de ellas es mediante el evento created en nuestro objeto VM. Recorriendo nuestro Array de tareas con un forEach le añadimos una nueva propiedad (editing) a cada tarea:

created: function () {
    this.tasks.forEach(function (task) {
        this.$set(task, 'editing', false);
    }.bind(this));
}

Vue.js usa una serie de getters y setters que le permiten detectar cambios en las propiedades del objeto y realizar los cambios necesarios en la vista, es por esta razón que usamos el método $set de Vue.js para declarar una nueva propiedad. El primer valor que le pasamos es el objeto, el segundo el nombre de la propiedad que queremos añadir y el tercero el valor de dicha propiedad.

En nuestro ejemplo usamos .bind() para enlazar nuestra función al objeto VM, si no sabes cómo funciona .bind() puedes verlo aquí.

Sin embargo esta primera forma se vuelve un poco complicada y no es la más optima porque editing realmente no forma parte del objeto task. editing es únicamente una propiedad que estamos usando para nuestra interfaz. Una mejor manera de definir esta propiedad es hacerlo como parte de los datos del componente app-task.

Vue.component('app-task', {
    data: function () {
        return {
            editing: false,
            draft: ''
        };
    },
    ...

Para que nuestro objeto data sea único para cada componente debemos colocarlo dentro de una función, como se muestra en el ejemplo anterior. Esto solo debemos hacerlo dentro de nuestros componentes y no en el objeto VM principal.

Definiendo la propiedad editing dentro del componente app-task la propiedad no forma parte de la tarea si no de nuestro componente. También cambiamos el borrador (draft) debido a que este ya no forma parte del objeto VM principal. Para acceder a esta propiedad modificamos nuestros métodos edit, update y discard y en lugar de hacer referencia a editing con this.task lo hacemos directamente con this ya que editing ahora forma parte de los datos del componente y no de la tarea:

edit: function () {
    ...
    // Antes: this.task.editing = true;
    this.editing = true;
},
edit: function () {
    ...
    // Antes: this.task.editing = false;
    this.editing = false;
},
discard: function () {
    this.editing = false;
}

Dentro de nuestra plantilla HTML también debemos modificar las referencias a editing:

...
<!-- Antes -->
<li class="list-group-item" 
    :class="{editing: task.editing, completed: !task.pending}">
    ...
</li>
<!-- Después -->
<li class="list-group-item" 
    :class="{editing: editing, completed: !task.pending}">
    ...
</li>
Únete a nuestra comunidad en Discord y comparte con los usuarios y autores de Styde, 100% gratis.

Únete hoy

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.

Lección anterior Representación de un registro como un componente en Vue.js 2 Lección siguiente Uso de eventos personalizados para comunicar componentes en Vue 2