Creando Animaciones y Transiciones Fluídas en Vue 3 con Transition y TransitionGroup
Descubre cómo dar vida a tus aplicaciones web en Vue 3 mediante la implementación de animaciones y transiciones fluidas para elementos individuales y listas dinámicas utilizando clases CSS y JavaScript.
Introducción a las Animaciones en Vue 3 🚀
Las animaciones y transiciones son elementos fundamentales en el desarrollo web moderno. No solo mejoran la estética visual de una aplicación, sino que también proporcionan una experiencia de usuario (UX) superior al guiar la atención del usuario, indicar cambios de estado y suavizar la aparición o desaparición de elementos en el DOM.
En Vue 3, manejar estas animaciones es sumamente sencillo gracias al componente nativo <Transition> y su contraparte para listas <TransitionGroup>. A lo largo de este tutorial completo, exploraremos cómo aprovechar al máximo estas herramientas para transformar interfaces estáticas en experiencias dinámicas y atractivas.
El Componente nativo 🎬
Cuando un elemento envuelto en el componente <Transition> es insertado o eliminado del DOM, Vue detecta automáticamente si el elemento tiene transiciones CSS o animaciones aplicadas. Si es así, añade o remueve clases CSS en momentos específicos del ciclo de vida de la transición.
Las 6 Clases de Transición
Para entender cómo opera el componente <Transition>, es vital conocer las seis clases que Vue inyecta automáticamente durante el proceso:
| Clase CSS | Descripción | Momento de Aplicación |
|---|---|---|
v-enter-from | Estado inicial de entrada. | Se añade antes de insertar el elemento, se quita un fotograma después. |
v-enter-active | Estado activo de entrada. | Se aplica durante toda la fase de entrada (desde el inicio hasta que termina la transición). |
v-enter-to | Estado final de entrada. | Se añade un fotograma después de la inserción, se quita al finalizar la transición. |
v-leave-from | Estado inicial de salida. | Se añade inmediatamente cuando se activa la transición de salida. |
v-leave-active | Estado activo de salida. | Se aplica durante toda la fase de salida (desde el inicio hasta que desaparece el elemento). |
v-leave-to | Estado final de salida. | Se añade un fotograma después de iniciar la salida, se quita al terminar. |
Ejemplo Práctico: Desvanecimiento Simple (Fade)
Vamos a construir nuestro primer ejemplo implementando una transición de desvanecimiento (fade) en un componente de Vue 3 utilizando Composition API.
<script setup>
import { ref } from 'vue'
const mostrar = ref(true)
</script>
<template>
<div class="demo-container">
<button @click="mostrar = !mostrar">
{{ mostrar ? 'Ocultar' : 'Mostrar' }} Mensaje
</button>
<Transition>
<p v-if="mostrar" class="mensaje">¡Hola, este texto se anima suavemente!</p>
</Transition>
</div>
</template>
<style>
.mensaje {
padding: 1rem;
background-color: #e0f2fe;
border-left: 4px solid #0284c7;
margin-top: 1rem;
}
/* Definimos las clases de transición */
.v-enter-active,
.v-leave-active {
transition: opacity 0.5s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
</style>
Transiciones con Nombres Personalizados 🏷️
A medida que tu aplicación crezca, necesitarás múltiples transiciones con comportamientos diferentes. Para evitar conflictos entre clases CSS, puedes utilizar la propiedad name en el componente <Transition>.
Ejemplo de Transición 'Slide' (Desplazamiento)
Imagina que queremos que un elemento se desplace desde la derecha al aparecer:
<script setup>
import { ref } from 'vue'
const activo = ref(false)
</script>
<template>
<button @click="activo = !activo">Alternar Desplazamiento</button>
<Transition name="slide">
<div v-if="activo" class="caja-deslizante">
Panel Lateral Animado
</div>
</Transition>
</template>
<style>
.caja-deslizante {
width: 250px;
padding: 20px;
background: #f3f4f6;
border: 1px solid #d1d5db;
}
.slide-enter-active,
.slide-leave-active {
transition: transform 0.4s ease, opacity 0.4s ease;
}
.slide-enter-from,
.slide-leave-to {
transform: translateX(50px);
opacity: 0;
}
</style>
Animaciones en Listas con 📋
Mientras que el componente <Transition> está diseñado para un solo elemento o nodo raíz, <TransitionGroup> se utiliza para manejar listas donde múltiples elementos pueden ser añadidos, eliminados o reordenados.
Características Clave de TransitionGroup:
Ejemplo Práctico: Lista de Tareas Dinámica
<script setup>
import { ref } from 'vue'
const tareas = ref(['Aprender Vue 3', 'Dominar TransitionGroup', 'Crear una App Increíble'])
const nuevaTarea = ref('')
const agregarTarea = () => {
if (nuevaTarea.value.trim() !== '') {
tareas.value.push(nuevaTarea.value)
nuevaTarea.value = ''
}
}
const eliminarTarea = (index) => {
tareas.value.splice(index, 1)
}
</script>
<template>
<div class="lista-container">
<input v-model="nuevaTarea" @keyup.enter="agregarTarea" placeholder="Escribe una nueva tarea..." />
<button @click="agregarTarea">Agregar</button>
<TransitionGroup name="lista" tag="ul">
<li v-for="(tarea, index) in tareas" :key="tarea" class="item-lista">
<span>{{ tarea }}</span>
<button @click="eliminarTarea(index)">X</button>
</li>
</TransitionGroup>
</div>
</template>
<style>
.lista-enter-active,
.lista-leave-active {
transition: all 0.5s ease;
}
.lista-enter-from,
.lista-leave-to {
opacity: 0;
transform: translateX(30px);
}
/* Animación para los elementos que cambian de posición */
.lista-move {
transition: transform 0.5s ease;
}
.item-lista {
display: flex;
justify-content: space-between;
padding: 8px 12px;
margin-top: 5px;
background: #f9fafb;
border: 1px solid #e5e7eb;
}
</style>
Integración con Librerías de Terceros (Animate.css) 🎨
Si no deseas escribir tus propias animaciones CSS desde cero, puedes integrar fácilmente librerías externas como Animate.css utilizando atributos de clase dedicados en el componente <Transition>.
Atributos de Clase Personalizados:
- enter-from-class
- enter-active-class
- enter-to-class
- leave-from-class
- leave-active-class
- leave-to-class
Ejemplo de Integración
<template>
<Transition
name="custom"
enter-active-class="animate__animated animate__fadeInDown"
leave-active-class="animate__animated animate__fadeOutUp"
>
<p v-if="mostrar">¡Animado con Animate.css!</p>
</Transition>
</template>
Ganchos de JavaScript para Animaciones Avanzadas ⚙️
Cuando las animaciones CSS se quedan cortas (por ejemplo, al crear efectos basados en física, animaciones de canvas o librerías como GSAP), puedes recurrir a los ganchos de JavaScript proporcionados por el componente <Transition>.
Lista de Ganchos Disponibles:
@before-enter@enter@after-enter@enter-cancelled@before-leave@leave@after-leave@leave-cancelled
Ejemplo con JavaScript y GSAP
<script setup>
import { ref } from 'vue'
import gsap from 'gsap'
const visible = ref(false)
const onEnter = (el, done) => {
gsap.fromTo(el,
{ opacity: 0, scale: 0.2 },
{ opacity: 1, scale: 1, duration: 0.5, onComplete: done }
)
}
const onLeave = (el, done) => {
gsap.to(el,
{ opacity: 0, scale: 0.2, duration: 0.5, onComplete: done }
)
}
</script>
<template>
<button @click="visible = !visible">Alternar GSAP</button>
<Transition
@enter="onEnter"
@leave="onLeave"
:css="false"
>
<div v-if="visible" class="caja-gsap">
Animado con GSAP
</div>
</Transition>
</template>
<style>
.caja-gsap {
width: 150px;
height: 150px;
background: #10b981;
color: white;
display: flex;
align-items: center;
justify-content: center;
}
</style>
Resumen y Buenas Prácticas 🎯
Las transiciones y animaciones en Vue 3 aportan un valor estético y funcional incalculable a cualquier desarrollo web moderno. Para concluir, repasemos los puntos más importantes:
- Utiliza <Transition> para elementos individuales y <TransitionGroup> para colecciones de elementos.
- Prioriza propiedades optimizadas para GPU como transform y opacity.
- Aprovecha las clases personalizadas para integrar librerías externas como Animate.css.
- Utiliza ganchos de JavaScript cuando requieras un control milimétrico o interpolaciones complejas.
¿Preguntas Frecuentes (FAQ)
¿Puedo animar elementos que se muestran con v-show? Sí, el componente Transition funciona exactamente igual tanto con v-if como con v-show. ¿Por qué mi TransitionGroup no anima el movimiento? Asegúrate de haber definido las reglas para la clase .v-move y que cada hijo tenga un atributo :key único.Tutoriales relacionados
- Aprovechando la API de Contexto en Vue 3 para la Inyección de Dependencias (Provide/Inject)intermediate18 min
- Migrando de Options API a Composition API en Vue 3: Una Guía Prácticaintermediate15 min
- Anatomía del Montaje: Ciclo de Vida de un Componente Vue 3 en Profundidadintermediate18 min
- Validación de Formularios Reactivos en Vue 3 con VeeValidate y Yup: Guía Completaintermediate20 min
- Control de Acceso Basado en Roles (RBAC) en Vue 3 con Directivas Personalizadas y Vue Routerintermediate20 min
Comentarios (0)
Aún no hay comentarios. ¡Sé el primero!