Unidad 12: Renderizado Condicional en Vue.js
Vue.js ofrece herramientas poderosas para controlar la visualización de elementos en tu interfaz de usuario basándose en condiciones específicas. Esto se logra mediante las directivas v-if, v-else-if, v-else y v-show.
12.1 v-if: Renderizado Condicional Real
La directiva v-if permite incluir o excluir elementos del DOM en función de una expresión booleana.
Uso básico:
Ejemplo de v-if en Vue.js
En este ejemplo, el párrafo solo se renderiza si isVisible es true. Al hacer clic en el botón, se alterna su visibilidad.
Consideraciones:
v-ifelimina y recrea el elemento en el DOM según la condición, lo que puede ser más costoso en términos de rendimiento si la condición cambia con frecuencia.- Es recomendable usar
v-ifcuando la condición no cambia con frecuencia.
12.2 v-else y v-else-if: Manejo de Alternativas
Estas directivas complementan a v-if, permitiendo manejar múltiples condiciones de manera secuencial.
Uso de v-else-if y v-else:
Ejemplo de v-else-if y v-else en Vue.js
<template>
<div>
<p v-if="status === 'loading'">Cargando...</p>
<p v-else-if="status === 'error'">Error al cargar datos.</p>
<p v-else>Contenido cargado exitosamente.</p>
</div>
</template>
<script>
export default {
data() {
return {
status: 'loading' // Puede ser 'loading', 'error' o 'loaded'
};
}
};
</script>
En este caso, se evalúan múltiples estados y se renderiza el bloque correspondiente según el valor de status.
Nota
v-else-ifse utiliza para agregar condiciones adicionales después de unv-if.v-elsese utiliza para manejar el caso en que ninguna de las condiciones anteriores se cumple.
12.3 v-show: Alternativa para Mostrar/Ocultar Elementos
La directiva v-show también permite controlar la visibilidad de un elemento, pero a diferencia de v-if, el elemento siempre se renderiza en el DOM y solo se oculta o muestra cambiando su propiedad CSS display.
Uso básico:
Ejemplo de v-show en Vue.js
Consideraciones:
v-showes más eficiente si la visibilidad del elemento cambia con frecuencia, ya que no implica la destrucción y recreación del DOM.- Sin embargo, el elemento siempre estará presente en el DOM, lo que puede no ser deseable si se trata de contenido sensible o pesado.
12.4 Uso de v-if con <template>: Renderizado de Múltiples Elementos
Si necesitas aplicar v-if a múltiples elementos adyacentes, puedes utilizar la etiqueta <template> como contenedor sin que se refleje en el DOM final.
Ejemplo:
En este caso, <template> actúa como un fragmento que agrupa múltiples elementos sin agregar un nodo extra al DOM.
Nota
v-if no es compatible con <template> en Vue.js 2.x, pero esta limitación se ha eliminado en Vue.js 3.x.
12.5 Comparativa entre v-if y v-show
| Característica | v-if |
v-show |
|---|---|---|
| Renderizado Inicial | No renderiza el elemento si la condición es falsa. | Renderiza el elemento y lo oculta con CSS si la condición es falsa. |
| Eficiencia | Más eficiente si la condición rara vez cambia. | Más eficiente si la condición cambia con frecuencia. |
| Visibilidad | Añade o elimina el elemento del DOM. | Alterna la visibilidad mediante CSS. |
| Uso Recomendado | Condiciones que rara vez cambian. | Condiciones que cambian con frecuencia. |
v-if: Realiza un renderizado condicional completo, añadiendo o eliminando el elemento del DOM según la condición. Es más adecuado cuando la condición no cambia frecuentemente.v-show: Solo alterna la visibilidad del elemento mediante CSS, manteniéndolo siempre en el DOM. Es más eficiente cuando la visibilidad del elemento cambia con frecuencia.
Resumen
- Usa
v-ifcuando la condición rara vez cambia y deseas evitar la renderización inicial del elemento. - Usa
v-showcuando la condición cambia con frecuencia y necesitas un cambio de visibilidad más eficiente.
12.6 Aplicación a nuestro ejemplo ToDo
Ahora es el momento de añadir una de las funciones principales que aún nos falta: la posibilidad de editar elementos de la lista de tareas. Para ello, aprovecharemos las funciones de renderizado condicional de Vue ( v-if y v-else) para alternar entre la vista de elementos de la lista y una vista de edición donde se pueden actualizar las etiquetas. También veremos cómo añadir la función para eliminar elementos de la lista.
12.6.1 Creación de un componente para la edición de tareas
Podemos empezar creando un componente independiente para gestionar la función de edición. En tu directorio components, crea un archivo llamado ToDoItemEditForm.vue. Copia el siguiente código en ese archivo:
código de ToDoItemEditForm.vue
<template>
<form class="stack-small" @submit.prevent="onSubmit">
<div>
<label class="edit-label">Edit Name for "{{label}}"</label>
<input
:id="id"
type="text"
autocomplete="off"
v-model.lazy.trim="newLabel" />
</div>
<div class="btn-group">
<button type="button" class="btn" @click="onCancel">
Cancel
<span class="visually-hidden">editing {{label}}</span>
</button>
<button type="submit" class="btn btn__primary">
Save
<span class="visually-hidden">edit for {{label}}</span>
</button>
</div>
</form>
</template>
<script>
export default {
props: {
label: {
type: String,
required: true,
},
id: {
type: String,
required: true,
},
},
data() {
return {
newLabel: this.label,
};
},
methods: {
onSubmit() {
if (this.newLabel && this.newLabel !== this.label) {
this.$emit("item-edited", this.newLabel);
}
},
onCancel() {
this.$emit("edit-cancelled");
},
},
};
</script>
<style scoped>
.edit-label {
font-family: Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #0b0c0c;
display: block;
margin-bottom: 5px;
}
input {
display: inline-block;
margin-top: 0.4rem;
width: 100%;
min-height: 4.4rem;
padding: 0.4rem 0.8rem;
border: 2px solid #565656;
}
form {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
form > * {
flex: 0 0 100%;
}
</style>
Revisar
Nota Revise el código anterior y luego lea la descripción a continuación para asegurarse de comprender todo lo que hace el componente antes de continuar. Esta es una forma útil de reforzar todo lo aprendido hasta ahora.
Este código configura la función de edición. Creamos un formulario con un campo <input> para editar el nombre de nuestra tarea.
Hay un botón "Guardar" y un botón "Cancelar":
- Cuando se hace clic en el botón "Guardar", el componente emite la nueva etiqueta a través de un
evento item-edited. - Cuando se hace clic en el botón "Cancelar", el componente lo señala emitiendo un evento
edit-cancelled.
12.6.2 Añadir la función de edición a la lista de tareas
Antes de añadir elementos ToDoItemEditForm a nuestra aplicación, necesitamos realizar algunas modificaciones en nuestro componente ToDoItem. En concreto, necesitamos añadir una variable para saber si el elemento se está editando y un botón para activar o desactivar dicha variable. También añadiremos un botón Delete, ya que la eliminación está estrechamente relacionada.
Actualice su plantilla ToDoItem como se muestra a continuación:
ToDoItem
Hemos agregado un envoltorio alrededor <div> de toda la plantilla para fines de diseño.
También hemos agregado los botones "Editar" y "Eliminar":
- Al hacer clic en el botón "Editar", se activará la visualización del componente
ToDoItemEditFormpara que podamos usarlo para editar nuestra tarea, mediante una función de controlador de eventos llamadatoggleToItemEditForm(). Este controlador establecerá un indicadorisEditingcomo verdadero. Para ello, primero debemos definirlo dentro de nuestra propiedaddata(). - Al hacer clic en el botón "Eliminar", se eliminará la tarea pendiente mediante una función de controlador de eventos llamada
deleteToDo(). En este controlador, emitiremos un eventoitem-deleteda nuestro componente principal para que la lista se actualice.
Definamos nuestros controladores de clic y la bandera isEditing necesaria.
Agregue isEditing a continuación su punto de datos existente isDone:
Ahora agregue sus métodos dentro de una propiedad de métodos, justo debajo de su data()propiedad:
12.6.3 Añadir renderizado condicional a la lista de tareas
Ahora tenemos una bandera isEditing que podemos usar para indicar si el elemento se está editando (o no). Si isEditing es verdadero, queremos usar esa bandera para mostrar "our" ToDoItemEditForm en lugar de la casilla de verificación. Para ello, usaremos otra directiva de Vue: v-if.
La directiva v-if solo renderizará un bloque si el valor que se le pasa es verdadero. Esto es similar al funcionamiento de una sentencia if en JavaScript. v-if también cuenta con directivas v-else-ify correspondientes v-else para proporcionar el equivalente de JavaScript else ify elsela lógica dentro de las plantillas de Vue.
Es importante tener en cuenta que los bloques v-else y v-else-if deben ser el primer hermano de un bloque v-if v-else-if; de lo contrario, Vue no los reconocerá. También puedes adjuntarlos v-if a una etiqueta <template> si necesitas renderizar condicionalmente una plantilla completa.
Por último, puedes usar un v-if + v-else en la raíz de tu componente para mostrar solo uno de los bloques, ya que Vue solo renderiza uno a la vez. Lo haremos en nuestra aplicación, ya que nos permitirá reemplazar el código que muestra nuestra tarea pendiente con el formulario de edición.
En primer lugar, agregue v-if="!isEditing" a la raíz <div>de su componente ToDoItem:
A continuación, debajo de esa etiqueta <div> de cierre, agregue la siguiente línea:
También necesitamos importar y registrar el componenete ToDoItemEditForm para poder usarlo dentro de esta plantilla. Agrega esta línea al principio del elemento <script>:
Y agregue una propiedad components encima de la propiedad props dentro del objeto componente:
Ahora, si vas a tu aplicación y haces clic en el botón "Editar" de un elemento de la tarea pendiente, deberías ver la casilla de verificación reemplazada con el formulario de edición.

Sin embargo, actualmente no hay forma de volver atrás. Para solucionarlo, necesitamos agregar más controladores de eventos a nuestro componente.
12.6.4 Añadir controladores de eventos para la edición de tareas
Primero, necesitamos agregar un método itemEdited() a la propiedad methods de nuestro componente ToDoItem. Este método debe tomar la etiqueta del nuevo elemento como argumento, emitir un evento itemEdited al componente principal y establecer isEditing a false.
Agreguelo ahora, debajo de sus métodos existentes:
A continuación, necesitaremos un método editCancelled(). Este método no acepta argumentos y solo sirve para establecer valor de retorno de isEditing a false. Agregue este método debajo del anterior:
Por último, en esta sección, agregaremos controladores de eventos para los eventos emitidos por el componente ToDoItemEditForm y adjuntaremos los métodos apropiados a cada evento.
Actualice su elemento <to-do-item-edit-form></to-do-item-edit-form> para que se vea así:
12.6.5 Añadir la función de eliminación de tareas
Ahora podemos alternar entre el formulario de edición y la casilla de verificación. Sin embargo, no hemos gestionado la actualización del array ToDoItems en ToDoList. Para solucionarlo, necesitamos escuchar el evento item-edited y actualizar la lista según corresponda. También queremos gestionar el evento de eliminación para poder eliminar elementos de la lista de tareas.
Agregue los siguientes métodos nuevos a su objeto ToDoList de componente , debajo de los métodos existentes dentro de la propiedad methods:
A continuación, agregaremos los escuchas de eventos para los eventos item-deletedy item-edited:
- Para
item-deleted, necesitarás pasar elitem.idal método. - Para
item-edited, deberás pasar la variable especialitem.idy$event. Esta es una variable especial de Vue que se usa para pasar datos de eventos a los métodos. Al usar eventos HTML nativos (comoclick), esto pasará el objeto de evento nativo a tu método.
Actualice la llamada <to-do-item></to-do-item> dentro de la plantilla ToDoList.vue para que se vea así:
¡Y ahí lo tienes! ¡Ahora deberías poder editar y eliminar elementos de la lista!
12.6.6 Corrección de un error con el estado isDone
Esto va genial hasta ahora, pero hemos introducido un error al añadir la función de edición. Prueba esto:
- Marque (o desmarque) una de las casillas de verificación de tareas pendientes.
- Presione el botón "Editar" para ese elemento de la tarea.
- Cancele la edición presionando el botón "Cancelar".
Observa el estado de la casilla de verificación después de cancelar: la aplicación no solo ha olvidado el estado de la casilla, sino que el estado de "completado" de esa tarea ahora está desfasado. Si intentas marcarla (o desmarcarla) de nuevo, el recuento de completados cambiará al revés de lo esperado. Esto se debe a que el valor interno isDone de data solo se proporciona un valor a this.done al cargar el componente.
Afortunadamente, solucionar este problema es bastante fácil: podemos hacerlo convirtiendo nuestro elemento isDone de datos en una propiedad calculada, otra ventaja de las propiedades calculadas es que preservan la reactividad , lo que significa (entre otras cosas) que su estado se guarda cuando la plantilla cambia, como ocurre ahora con la nuestra.
Entonces, implementemos la solución en ToDoItem.vue:
Primero eliminar la siguiente línea del interior de nuestra propiedad data():
Segundo agregue el siguiente bloque debajo del bloque data() { }:
Ahora, cuando guardes y vuelvas a cargar, verás que el problema está resuelto: el estado de la casilla de verificación ahora se conserva cuando cambias entre plantillas de elementos de tarea pendiente.
12.6.7 Comprender la maraña de acontecimientos
Una de las partes más potencialmente confusas es la maraña de eventos estándar y personalizados que hemos usado para activar toda la interactividad en nuestra aplicación. Para comprender esto mejor, conviene crear un diagrama de flujo, una descripción o un diagrama que muestre qué eventos se emiten y dónde, dónde se escuchan y qué sucede al activarse.
Aplicación.vue
<to-do-form> escucha para:
- evento emitido
todo-addedpor el métodoonSubmit()dentro del componenteToDoFormal enviar el formulario. Resultado : el método invocadoaddToDo()para añadir un nuevo elemento de la lista de tareas a la matrízToDoItems.
<to-do-item> escucha para:
- evento emitio
checkbox-changedpor la casilla de verificación<input>dentro del componeneteToDoItemal estar marcada o desmarcada. Resultado: el método invicadoupdateDoneStatus()para actualizar el estado de finalización del elemento de la tarea asociada. - Evento emitido
item-deletedpor el métododeleteToDo()dentro del componenteToDoItemal presionar el botón "Eliminar". Resultado: método invocadodeleteToDo()para eliminar el elemento de la tarea asociada. - Evento emitido
item-editedpor el métodoitemEdited()dentro del componenteToDoItemcuando se escucha correctamente. Sí, se trata de una cadena de dos eventos diferentesitem-edited. Resultado: método invocadoeditToDo()para actualizar la etiqueta asociada al elementotodo item.
ToDoForm.vue
<form> escucha el evento submit. Resultado: el método onSubmit() es invocado, que verifica que la nueva etiqueta no esté vacía, emite el evento todo-added (que se escucha dentro de ToDoList.vue y, finalmente, borra la nueva etiqueta <input>.
ToDoItem.vue
El <input> of type="checkbox" escucha eventos change. Resultado: el evento checkbox-changed emitido cuando se marca o desmarca la casilla de verificación (que luego se escucha internamente ToDoList.vue.
El <button> "Editar" detecta el evento click. Resultado : se invoca el método toggleToItemEditForm(), que cambia this.isEditing a true, lo que a su vez muestra el formulario de edición del elemento de la lista al volver a renderizar.
el <button> "Eliminar" detecta el evento click. Resultado : se invoca el método deleteToDo(), que emite el evento item-deleted (que se detecta internamente ToDoList.vue).
<to-do-item-edit-form> escucha para:
-
El evento
item-editedemitido por el métodoonSubmit()dentro del componenteToDoItemEditFormcuando el formulario se envía correctamente. Resultado: se invoca el métodoitemEdited(), que emite el eventoitem-edited(que se escucha dentro deToDoList.vue) y reestablece el valor dethis.isEditingafalse, de modo que el formulario de edición ya no se muestra al volver a renderizar. -
El evento
edit-cancelledemitido por el métodoonCancel()dentro del componeneteToDoItemEditFormal hacer clic en el botón "Cancelar". Resultado: se invoa al métodoeditCancelled(), ythis.isEditingvuelve a establecerse enfalse, por lo que el formulario de edición ya no se muestra al volver a renderizar.
[ToDoItemEditForm.vue]
<form> espera el evento submit. Resultado: se invoca el método onSubmit(), que verifica si el nuevo valor de etiqueta no está en blanco ni es igual al anterior. De ser así, emite el evento item-edited (que luego se escucha dentro de ToDoIntem).
El botón "Cancelar" detecta el evento click. Resultado: se invoca el método onCancel(), que emite el evento edit-cancelled (que se detecta dentro de ToDoItem.vue).
12.6.8 Resumen
Este artículo ha sido bastante intenso y hemos cubierto muchos temas. Ahora tenemos la función de editar y eliminar en nuestra aplicación. Nos acercamos al final de nuestras prácticas sobre Vue. La última función que veremos es la gestión del foco, o dicho de otro modo, cómo podemos mejorar la accesibilidad del teclado de nuestra aplicación.
He revisado la Unidad 12: Renderizado Condicional en Vue.js y todo está bien estructurado. Ahora, te propongo una actividad final basada en este tema, específicamente para el Blog.
Actividad Final: Implementación de Renderizado Condicional en el Blog
📌 Objetivo: Implementar la funcionalidad de mostrar diferentes estados de una entrada del blog (por ejemplo, "Cargando", "Error" y "Contenido cargado") utilizando las directivas de renderizado condicional (v-if, v-else-if, v-else) en Vue.js.
📌 Pasos a seguir:
1️⃣ Crear un estado status en BlogList.vue que determine si los datos están siendo cargados, si hubo un error o si ya se cargaron correctamente.
2️⃣ Utilizar las directivas v-if, v-else-if y v-else para mostrar diferentes mensajes en función del valor de status.
3️⃣ Agregar un button para simular los estados de carga y error mediante un cambio manual en el estado de status.
🔒 Solución Final (oculta inicialmente)
Código de BlogList.vue con Renderizado Condicional:
Solución a la Actividad Final
<template>
<div class="container mt-4">
<h2 class="text-center">Entradas del Blog</h2>
<!-- Estado: Cargando -->
<p v-if="status === 'loading'">Cargando...</p>
<!-- Estado: Error -->
<p v-else-if="status === 'error'">Error al cargar los datos.</p>
<!-- Estado: Contenido Cargado -->
<div v-else>
<ul>
<li v-for="(post, index) in posts" :key="index">
{{ post.titulo }}
</li>
</ul>
</div>
<button @click="simulateLoading">Simular Carga</button>
<button @click="simulateError">Simular Error</button>
</div>
</template>
<script>
export default {
data() {
return {
status: 'loading', // 'loading', 'error', 'loaded'
posts: [
{ titulo: 'Primer Post', contenido: 'Contenido de la primera entrada' },
{ titulo: 'Segundo Post', contenido: 'Contenido de la segunda entrada' }
]
};
},
methods: {
simulateLoading() {
this.status = 'loading';
setTimeout(() => {
this.status = 'loaded';
}, 2000);
},
simulateError() {
this.status = 'error';
}
}
};
</script>
Explicación de la solución:
v-if="status === 'loading'": Muestra el mensaje "Cargando..." cuando el estado es'loading'.v-else-if="status === 'error'": Muestra un mensaje de error cuando el estado es'error'.v-else: Muestra el contenido de las entradas cuando el estado es'loaded'.- Simulación de estados: Los botones permiten cambiar el estado a
'loading'o'error', simulando el comportamiento de una aplicación real.
Objetivo de la actividad:
Con esta actividad, los alumnos aprenderán a usar el renderizado condicional de Vue.js para gestionar la visualización dinámica de contenido basado en el estado de la aplicación, lo que mejora la experiencia del usuario al interactuar con la interfaz.