Tutorial de VueJS: Aprende creando un programa sencillo.



Con este tutorial aprenderás algunas de las funciones básicas de VueJS y te harás una idea en poco tiempo sobre como es la programación de aplicaciones web usando VueJS.

Con esta guía podrás crear una aplicación sencilla de control de tareas pendientes, puedes ver el resultado y probar la aplicación que crearemos. Y también puedes descargar el código fuente completo y totalmente gratis.

Tendrás algunos ejercicios que debes resolver para que puedas despejar tus dudas y aprender un poco más.

Versión en video

Si prefieres ver un video, aquí está la versión del artículo para YouTube, si no, solo salta a la siguiente sección después del video.

Como crear una aplicación basada en VueJS

VueJS es un framework basado de JavaScript, así que podemos probarlo en nuestra propia computadora sin necesitar un servidor y como siempre la forma más sencilla es creando una página HTML e incluir la librería por medio de un enlace. Aquí hay un ejemplo básico.

<!DOCTYPE html>
<html lang="es">

<head>
  <meta charset="UTF-8">
  <title>Simple ToDo app</title>  
</head>

<body>
  <div id="todo-app">
      <h1>{{ header }}</h1>      
  </div>    
    
  <!-- Script cdn vue -->
  <script src="https://unpkg.com/vue@3"></script>

  <!-- vue app -->
  <script>
    const ToDoApp = Vue.createApp({
        data() {
            return {
            header: 'Tareas pendientes',
            }
        }    
    }).mount('#todo-app')
  </script>
</body>

</html>

Si copias el código anterior en un archivo y lo abres desde tu navegador verás algo como esto:

Ejemplo de una aplicación hecha con VueJS

Ahora repasemos el código más importante y nuevo, bloque por bloque.

<div id="todo-app">
    <h1>{{ header }}</h1>      
</div>

Esto es algo importante, debes agregar una etiqueta div con un ID único, esto servirá para montar la aplicación de VueJS sobre esta sección. Luego tenemos la palabra header encerrada es signos {{ }}.

Bueno, la palabra header no es más que una variable, la cual declaramos más adelante. Y los signos {{ }} se usan para decirle a la aplicación que debe evaluar la expresión que está ahí adentro e imprimir el resultado. En este caso va a imprimir el contenido de la variable.

Luego tenemos este código, que lo único que hace es cargar el framework de VueJS en nuestra aplicación desde un servidor CDN.

<!-- Script cdn vue -->
<script src="https://unpkg.com/vue@3"></script>

Finalmente, viene la parte más interesante que es en donde ingresamos el código de la aplicación.

<!-- vue app -->
  <script>
    const ToDoApp = Vue.createApp({
        data() {
            return {
            header: 'Tareas pendientes',
            }
        }    
    }).mount('#todo-app')
  </script>

En este caso es algo sencillo, primero debes notar que la aplicación se crea usando el método createApp y recibe como parámetro un objeto de JavaScript. El objeto contiene una función llamada data que regresa un objeto Json. De aquí sale la variable llamada header que usamos anteriormente.

Esta función solo regresa un objeto con una variable, pero podría haber regresado más variables, funciones y eventos que puedes usar en tu aplicación.

Finalmente, usa el método mount con el ID del div que incluimos al inicio. De esta forma, cualquier etiqueta HTML que está dentro de ese div, puede acceder a las variables, métodos y demás código de la aplicación de VueJS.

Práctica (Tu primera aplicación VueJS)

Si aún no lo has hecho, crea un archivo con el código que vimos al inicio, esto te servirá como base para el ejercicio.

El primer ejercicio es fácil, solo debes de cambiar el contenido de la variable header y volver a cargar la página para que veas como cambia el contenido. Esto te ayudará a entender como funciona el sistema de plantillas.

Ahora agrega una nueva variable e imprímela de forma similar a como se imprime el contenido de la variable header. Aquí hay una muestra de como podría quedar una parte del código (haz tú lo demás):

<script>
    const ToDoApp = Vue.createApp({
        data() {
            return {
            header: 'Tareas pendientes',
            contenido: 'Me gusta usar VueJS'
            }
        }    
    }).mount('#todo-app')
</script>

Renderizado de listas

Ahora vamos a ver lo fácil que es mostrar una lista de datos en la pantalla. Para ver como funciona voy a imprimir en pantalla una lista de tareas pendientes. El código completo es el siguiente:

<!DOCTYPE html>
<html lang="es">

<head>
  <meta charset="UTF-8">
  <title>Simple ToDo app</title>  
</head>

<body>
<div id="todo-app">
    <h1>{{ header }}</h1>      
    <ul>
        <li v-for="item in items" :key="item.id"> 
            {{ item.label }}            
        </li>
  </ul>
</div>    
    
  <!-- Script cdn vue -->
  <script src="https://unpkg.com/vue@3"></script>

  <!-- vue app -->
  <script>
    const ToDoApp = Vue.createApp({
        data() {
            return {
            header: 'Tareas pendientes',            
            items:[
                {id: 1, label:'Comprar leche', completada: false},
                {id: 2, label:'Aprender VueJS', completada: false},
                {id: 3, label:'Pagar la tarjeta de credito', completada: false},
            ]
            }
        }    
    }).mount('#todo-app')
  </script>
</body>

</html>

Si ejecutas este código, verás una página como esta:

Ejemplo de renderizado de listas en VueJS

Analicemos el código que hemos agregado, primero veamos este bloque:

  <ul>
      <li v-for="item in items" :key="item.id"> 
          {{ item.label }}            
      </li>    
  </ul>

Aquí tenemos una lista no ordenada y que tiene un solo elemento. Nos interesa los atributos que tiene la etiqueta <li>, vemos que tiene un atributo llamado v-for, este se usa para decir que este elemento se va a repetir para cada dato dentro de un arreglo (array) y en este caso el arreglo se llama items.

También le decimos que para cada elemento debe usar item.id como la llave que identifica de forma única cada elemento. Esto es especialmente útil, porque desde aquí podemos modificar un elemento.

Finalmente, se imprime un texto, y este se encuentra el item.label. Ahora veamos el siguiente fragmento de código:

items:[
                {id: 1, label:'Comprar leche', completada: false},
                {id: 2, label:'Aprender VueJS', completada: false},
                {id: 3, label:'Pagar la tarjeta de credito', completada: false},
            ]

Como puedes observar, únicamente agregamos una variable nueva, llamada items y consiste en un array de objetos, cada objeto posee información sobre las tareas a mostrar.

Práctica (Agrega una etiqueta en la lista)

Ahora intenta modificar el array de datos y agrega un campo más, llamado prioridad, este puede contener valores como: Alta, Media, Baja. Actualmente, el array de datos tiene los campos id, label y completada.

Luego muestra ese valor entre paréntesis a la par de cada descripción y que se muestre en la página web.

Manejo de entradas de usuario y métodos

Vamos a agregar más funcionalidad a nuestra aplicación, ahora podremos agregar tareas, eliminar tareas y marcarlas como completadas.

Agregar tareas (Manejo de entradas de usuario)

Lo primero que haremos es agregar una variable llamada tarea, en la misma sección en que creamos la variable header. Esta variable se usará más adelante para capturar el nombre de la tarea que se desea agregar.

Luego creamos un método llamado agregar, en donde simplemente agregamos un elemento más al array items. Aquí está esa parte del código:

<script>
    const ToDoApp = Vue.createApp({
        data() {
            return {
            header: 'Tareas pendientes',        
            tarea: '',
            items:[
                {id: 1, label:'Comprar leche', completada: false},
                {id: 2, label:'Aprender VueJS', completada: false},
                {id: 3, label:'Pagar la tarjeta de credito', completada: false},
            ]
            }
        },
        methods:
        {
            agregar()
            {
                if (this.tarea == '') {
                    return;
                }
                this.items.push({'id':Date.now(),'label':this.tarea, 'completada':false});
                this.tarea = '';                
            }
        }
    }).mount('#todo-app')
  </script>

Para finalizar esta parte, debemos agregar una etiqueta input para poder capturar el nombre de las tareas y llamar al método agregar cuando el usuario presione la tecla enter. Este es el código HTML, debes poner atención en que agregamos una etiqueta Input:

<div id="todo-app">
  <h1>{{ header }}</h1>   
  <input v-model="tarea" v-on:keyup.enter="agregar" type="text" placeholder="Escribe una tarea y presiona enter">           
  <ul>
      <li v-for="item in items" :key="item.id"> 
          {{ item.label }}            
      </li>    
  </ul>
</div>       

Ahora la aplicación se verá como esta, en donde hay una caja de texto para ingresar tareas nuevas

Manejo de entradas de usuario en VueJS

Voy a explicarte un poco este código. Cuando usas el atributo v-model="variable" estás sincronizando el valor de esa etiqueta con una de las variables de tu aplicación Vue, en este caso cuando alguien escriba sobre la caja de texto, el valor va a actualizarse también en la variable. Si, por otra parte, cambias la variable, también cambias el texto de esta caja de texto.

De esta forma puedes acceder fácilmente al contenido de la caja de texto.

Ahora solo falta explicar este atributo: v-on:keyup.enter="agregar". Aquí con v-on le dices que escuche un evento, luego dices que el evento que quieres escuchar es cuando alguien presione una tecla y la suelte (keyup), después le dices que la tecla que estás esperando es la tecla enter. Finalmente, le dices que al cumplirse todo lo anterior, que llame al método agregar, que definimos anteriormente.

Borrar tareas (Evento click)

Ahora vamos a permitir que el usuario pueda borrar una tarea, esto lo haremos en 3 pasos. Primero vamos a crear un método para borrar un elemento de nuestro arreglo de tareas:

 methods:
        {
            agregar()
            {
                if (this.tarea == '') {
                    return;
                }
                this.items.push({'id':Date.now(),'label':this.tarea, 'completada':false});
                this.tarea = '';                
            },
            borrar(id)
            {
                this.items = this.items.filter(el => el.id !== id);                 
            },
        }

El método borrar(id) hace uso de la función filter de JavaScript que permite crear un nuevo array aplicando un filtro, en ese caso le decimos que excluya el elemento con el id que deseamos borrar.

El segundo paso será incluir una librería de iconos, para mostrar el icono de un basurero a la par de cada tarea, esto lo haremos incluyendo la librería font awesome entre las etiquetas head.

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer" />

Como tercer y último paso vamos a agregar una etiqueta i con el icono del basurero y vamos a agregar el atributo @click="borrar(item.id).

<li v-for="item in items" :key="item.id"> 
    {{ item.label }}       
    <i class="fa-solid fa-trash-can" @click="borrar(item.id)"></i>
</li> 

Como puedes imaginar @click se usa para decir que queremos ejecutar algo cuando el usuario hace clic sobre un elemento. En este caso llamamos al método borrar cuando alguien hace clic sobre el icono que acabamos de agregar.

Borrar elementos en VueJS

Completar tareas (clases condicionales)

Si en lugar de borrar una tarea, deseas mostrarlas como completadas, solo debemos cambiar su estado y agregar una clase de CSS que nos permita visualizar la tarea como completada.

Primero vamos a crear un archivo CSS con este nombre main.css y este código adentro:

.completado {
  text-decoration:line-through;
}

Eso hará que el texto se muestre tachado. Luego incluimos el archivo CSS agregando este código en las etiquetas HEAD.

<link rel="stylesheet" href="main.css">

Ahora vamos a agregar un método que nos permita cambiar el estado de una tarea.

completar(tarea)
{
     tarea.completada = !tarea.completada;                
}

El método anterior recibe como parámetro la tarea a modificar y cambia el valor de campo completada. De esta forma, si lo presionas una vez la marca como completada y si la presionas de nuevo, revierte el cambio.

Ahora solo necesitamos cambiar el código que renderiza la plantilla HTML, voy a colocar el código completo que imprime la tarea y voy a explicarte los cambios.

<li v-for="item in items" :key="item.id"> 
   <span :class="(item.completada) ? 'completado' : ''">{{ item.label }}</span> 
   <i class="fa-solid fa-check" @click="completar(item)"></i>     
   <i class="fa-solid fa-trash-can" @click="borrar(item.id)"></i>
</li> 

Primero hay que notar que ahora, para mostrar el texto de la tarea, hemos agregado una etiqueta span, esta tiene una clase, pero la palabra class está precedida por dos puntos (:) eso significa que su contenido es dinámico y VueJs va a evaluar la expresión para asignar un valor a la clase.

En este caso uso una expresión ternaria para que cuando el valor item.competada es cierta, le asigne la clase completado, y de otra forma no le asigne nada.

Finalmente, agrego una etiqueta <i> con un icono y que llame al método completar cuando hagamos clic sobre el icono.

Ordenar tareas

No se ve bien, que cuando completas algunas tareas aún siguen revueltas las completadas con las pendientes. Vamos a solucionar esto creando un método para reordenar las tareas. Como VueJS es una librería reactiva, cuando se hace un cambio en los datos, actualiza la página web sin necesidad de recargarla.

Entonces, con solo ordenar el arreglo de datos, las tareas completadas se moverán hacia abajo.

Primero agrega este método, que usa el método de JS sort para ordenar un arreglo.

ordenar()
{
    this.items = this.items.sort((a, b) => {
        if (a.completada == false && b.completada == false) {
            return 0
        }

        if (a.completada == false) {
            return -1;
        }

        if (a.completada == true) {
            return 1;
        }
    });
}

Luego solo tienes que llamarlo al final de los métodos, completar y agregar

Ordenar un arreglo de datos con JS

Ahora, cuando agregues una tarea o la completes, todas las tareas se van a reordenar para mostrar abajo las completadas y arriba las pendientes.

Guardar datos en almacenamiento local

También necesitamos que las tareas se puedan guardar y leer del almacenamiento local, para que no perdamos nuestros datos.

Esto es realmente sencillo, primero vamos a crear un método que se encargue de guardar

guardar() 
{
    const parsed = JSON.stringify(this.items);
    localStorage.setItem('tareas', parsed);
}

Este método convierte el arreglo items en un objeto json representado en una cadena de texto, y lo almacena localmente en con una clave llamada tareas.

Ahora debemos llamar este método cuando agregamos una tarea, cuando la borramos o cuando la completamos.

Guardar información con vuejs en almacenamiento local

Leer datos del almacenamiento local

Ya guardamos los datos, ahora es tiempo de cargarlos desde el almacenamiento local en el momento en que nuestra aplicación es abierta.

Para esto vamos a usar un evento de VueJS llamado mounted, el código de este evento se ejecuta cuando se abre una aplicación y se han cumplido estas condiciones:

  • Todos sus componentes hijos síncronos han sido montados (esto no incluye componentes asíncronos o componentes dentro de árboles )
  • Su propio árbol DOM ha sido creado e insertado en el contenedor padre. Ten en cuenta que solo garantiza que el árbol DOM del componente está en el documento si el contenedor raíz de la aplicación también está en el documento.

En resumen, es cuando el código HTML ya se renderizó o ya se mostró la página, aunque aún no se hayan cargado algunas secciones asíncronas.

En el código vamos a agregar esto, justo debajo del código de la sección data():

mounted()  {
    if (localStorage.getItem('tareas')) 
    {
        try {
            this.items = JSON.parse(localStorage.getItem('tareas'));
            this.ordenar();
        } catch(e) {
            localStorage.removeItem('tareas');
        }
    }
},

Aquí hay una imagen de donde debes insertar el código. Si hiciste todo bien, ahora tu aplicación es 100% funcional y te cargará los datos que has guardado. Solo necesitamos agregar algunos detalles estéticos.

Ejemplo de código para cargar datos en el evento mounted de vuejs

Agregar estilos con Tailwind CSS

Ahora hagamos que la aplicación se vea mejor y para esto vamos a usar un framework CSS llamado Tailwind CSS.

No es recomendable hacer esto en un sistema de producción, pero para hacer esto más sencillo vamos a incluir el framework desde una red CDN.

Nota: no se recomienda porque al hacerlo incluyes la versión completa del framework haciéndolo más pesado, en cambio, lo recomendable es compilar tu propia versión para generar un archivo con solo lo que necesitas y con la posibilidad de personalizarlo.

Para esto solo agrega esto en las etiquetas HEAD

<script src="https://cdn.tailwindcss.com"></script>

Ahora solo debemos agregar algunas clases a las etiquetas HTML, vamos a comenzar centrando las tareas. Esto lo logramos agregando estas clases al div principal

<div id="todo-app" class="grid place-items-center">

Como puedes ver, Tailwind CSS funciona agregando clases predefinidas en los elementos para darles el formato que necesitas.

Ahora hagamos que nuestro cuadro de texto se vea mejor, al agregar un div y estas clases

<div class="grid grid-cols-1 w-96">
    <input v-model="tarea" v-on:keyup.enter="agregar" type="text" placeholder="Escribe una tarea y presiona enter" class="my-4 bg-gray-80 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2">        
</div>

Puedes hacer una pausa y guardar para ver los resultados hasta ahora. Para entender que hace algo puedes remover alguna clase y volver a cargar la aplicación y ver la diferencia.

Finalmente, necesitamos el estilo de la lista de tareas.

<div class="grid grid-cols-1 ">
    <ul>
            
        <li v-for="item in items" :key="item.id" class="group"> 
            <span :class="(item.completada) ? 'line-through' : ''">{{ item.label }}</span>
            <i class="fa-solid fa-check mx-4 opacity-0 group-hover:opacity-100" @click="completar(item)"></i> 
            <i class="fa-solid fa-trash-can mr-4 opacity-0 group-hover:opacity-100" @click="borrar(item.id)"></i>
        </li>
            
    </ul>
</div>

Si ejecutas ahora tu aplicación se verá así, he usado muchas clases y no puedo explicar todo en detalle en este tutorial porque el punto es aprender VueJS, pero quería mostrarte que también se pueden hacer aplicaciones con una estética agradable (y se puede dejar aún mejor de lo que lo hice yo)

Vista de la aplicación final creada con VueJS

Agregar animaciones nativas de VueJS

Esta es la parte final, en lugar de hacer que las tareas aparezcan y desaparezcan en un parpadeo, voy a agregarles una animación que ya viene predefinida en VueJS y que mejora instantáneamente tu aplicación.

Primero solo tienes que rodear la etiqueta<li> (que es lo que necesitamos animar) con etiquetas <transition-group> tal y como se mira en este código:

<transition-group name="list" tag="ul">
    <li v-for="item in items" :key="item.id" class="group"> 
        <span :class="(item.completada) ? 'line-through' : ''">{{ item.label }}</span>
        <i class="fa-solid fa-check mx-4 opacity-0 group-hover:opacity-100" @click="completar(item)"></i> 
        <i class="fa-solid fa-trash-can mr-4 opacity-0 group-hover:opacity-100" @click="borrar(item.id)"></i>
    </li>
</transition-group> 

Esto hará que todo el contenido se anime con una transición. Es importante que notes que tiene un atributo name con un valor list. Esto es importante porque ahora debemos de crear unas clases para configurar la animación.

En el archivo main.css que creamos anteriormente, debes de agregar este código:

.list-enter-active,
.list-leave-active {
  transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}

Observa que todas las clases inician con el nombre list, esto es porque le dimos ese nombre a la transición. Ahora intenta agregar o eliminar tareas y verás que tienen una transición suave.

Conclusiones

VueJS es una forma fácil de generar aplicaciones basadas en JavaScript. Usarlo puede ayudarte a desarrollar una aplicación en menos tiempo y con mejores resultados.

Si nunca antes lo has usado o estás pensando si vale la pena aprenderlo, te recomiendo que si lo aprendas, si en algún momento tienes problemas, no te preocupes porque hay mucha información y ejemplos sobre VueJS en internet.

Dime que te pareció VueJS o si estás usando un framework diferente en tus programas.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *