本文系统讲解 Vue 3 中 Transition 与 TransitionGroup 内置组件的核心机制,结合 CSS 类名与 JavaScript 钩子实现...
快速概述
在构建现代 Web 应用时,动画效果已成为提升用户体验的关键因素。Vue.js 作为主流前端框架,其内置的 Transition 和 TransitionGroup 组件为开发者提供了强大的动画能力。不同于第三方动画库,这些原生组件深度集成在 Vue 的响应式系统中,能够智能地处理元素的进入/离开动画以及列表变化的过渡效果。本教程适用于需要为单元素切换、列表增删排序等场景添加流畅交互的 Vue 3 开发者,前置环境要求为已安装 Vue 3 及支持 CSS 过渡的现代浏览器。
核心概念与原理
Transition 组件的核心机制基于六个动画阶段对应的 CSS 类名:v-enter-from(进入动画起始状态)、v-enter-active(进入动画过程)、v-enter-to(进入动画结束状态)、v-leave-from(离开动画起始状态)、v-leave-active(离开动画过程)、v-leave-to(离开动画结束状态)。实际项目中推荐使用自定义类名前缀代替默认的 v- 前缀,例如为 Transition 设置 name="fade" 后,对应的 CSS 就变为 fade-enter-active 等,这样可以避免全局样式冲突。当需要实现复杂动画逻辑时,JavaScript 钩子比 CSS 更灵活,Transition 提供了 before-enter、enter、after-enter、enter-cancelled、before-leave、leave、after-leave、leave-cancelled 等钩子函数。
实战步骤与代码
步骤 1:实现单元素过渡
使用 Transition 标签包裹需要动画的元素,通过 v-if 或 v-show 控制显示状态。以下代码展示了基础实现:
<template>
<button @click="show = !show">切换</button>
<Transition>
<p v-if="show">Hello Vue 3!</p>
</Transition>
</template>
<script setup> import { ref } from 'vue' const show = ref(true) </script>
<style> /* 定义进入/离开过程的过渡样式 */ .v-enter-active, .v-leave-active { transition: opacity 0.5s ease; } .v-enter-from, .v-leave-to { opacity: 0; } </style>
上述代码中,Transition 会自动在元素插入或移除时添加/删除对应 CSS 类名触发动画。
步骤 2:使用自定义名称与 JavaScript 钩子
为 Transition 设置 name 属性可自定义类名前缀,避免全局样式冲突。当需要弹性动画等复杂效果时,可结合 JavaScript 钩子与 GSAP 实现:
<Transition
name="fade"
@enter="onEnter"
@leave="onLeave"
>
<div v-if="visible">内容</div>
</Transition>
<script setup> import gsap from 'gsap'
function onEnter(el, done) { gsap.from(el, { duration: 0.8, opacity: 0, y: 30, ease: 'elastic.out(1, 0.5)', onComplete: done }) }
function onLeave(el, done) { gsap.to(el, { duration: 0.3, opacity: 0, onComplete: done }) } </script>
关键提示:必须在使用 JavaScript 动画时调用 done 回调,否则过渡会卡住,这是新手常犯的错误。
步骤 3:列表过渡与排序动画
TransitionGroup 专用于列表场景,可为列表项的插入、移除和移动添加动画。例如在电商后台管理系统中,使用 TransitionGroup 实现商品列表的排序动画,仅用 20 行代码就完成了传统 CSS 动画需要上百行才能实现的效果。
<TransitionGroup name="list" tag="ul">
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
</TransitionGroup>
<style> .list-enter-active, .list-leave-active { transition: all 0.5s ease; } .list-enter-from, .list-leave-to { opacity: 0; transform: translateX(30px); } /* 移动动画 */ .list-move { transition: transform 0.5s ease; } </style>
常见坑点与优化
- 忘记调用 done 回调:使用 JavaScript 钩子时,若未在动画完成后调用 done,过渡会卡住无法结束。
- 默认类名冲突:多个 Transition 共用默认 v- 前缀会导致样式互相干扰,务必为每个过渡设置独立的 name。
- 列表项缺少 key:TransitionGroup 要求每个子元素必须有唯一的 key,否则移动动画无法正确触发。
- 性能优化:优先使用 CSS 过渡而非 JavaScript 动画,因为 CSS 动画可由浏览器原生优化;对于复杂动画,建议使用 transform 和 opacity 属性而非 width、height 等触发重排的属性。
评论列表 0