Vue 3 过渡动画基础类名
1. 过渡动画概述
1.1 什么是过渡动画
过渡动画是指元素在进入或离开DOM时,通过CSS类名的切换实现的平滑过渡效果。Vue提供了内置的<transition>组件,用于处理元素的进入和离开动画。
1.2 过渡动画的应用场景
- 元素的显示/隐藏
- 组件的切换
- 路由的跳转
- 列表的增删改查
1.3 Vue过渡系统的特点
- 基于CSS类名的切换
- 支持CSS过渡和CSS动画
- 支持JavaScript钩子函数
- 支持自定义过渡类名
- 支持嵌套过渡
2. 过渡动画的基础类名
Vue的过渡系统会在元素进入或离开DOM时,自动添加和移除一系列CSS类名。这些类名遵循特定的命名规则,用于控制过渡的各个阶段。
2.1 基本过渡类名
当使用<transition name="fade">时,Vue会自动生成以下类名:
| 类名 | 描述 | 应用时机 |
|---|---|---|
fade-enter-from |
进入过渡的起始状态 | 元素被插入前添加,插入后移除 |
fade-enter-active |
进入过渡的激活状态 | 整个进入过渡期间应用,插入前添加,过渡完成后移除 |
fade-enter-to |
进入过渡的结束状态 | 元素被插入后添加,过渡完成后移除 |
fade-leave-from |
离开过渡的起始状态 | 离开过渡开始时添加,离开过渡触发后立即移除 |
fade-leave-active |
离开过渡的激活状态 | 整个离开过渡期间应用,离开过渡开始时添加,过渡完成后移除 |
fade-leave-to |
离开过渡的结束状态 | 离开过渡开始后添加,过渡完成后移除 |
2.2 过渡类名的生命周期
进入过渡:
- 元素被插入DOM前:添加
fade-enter-from和fade-enter-active类 - 元素被插入DOM后:移除
fade-enter-from类,添加fade-enter-to类 - 过渡结束后:移除
fade-enter-active和fade-enter-to类
离开过渡:
- 离开过渡触发时:添加
fade-leave-from和fade-leave-active类 - 下一帧:移除
fade-leave-from类,添加fade-leave-to类 - 过渡结束后:移除
fade-leave-active和fade-leave-to类,同时移除元素
2.3 过渡类名的优先级
Vue的过渡类名具有较高的优先级,会覆盖普通的CSS类名。这是因为Vue在编译时会为过渡类名添加组件实例的唯一属性选择器,例如:
.fade-enter-active[data-v-7ba5bd90] {
/* 过渡样式 */
}3. 基本使用示例
3.1 CSS过渡效果
<template>
<div>
<button @click="show = !show">Toggle</button>
<transition name="fade">
<div v-if="show" class="box">
Hello Transition
</div>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
show: true
}
}
}
</script>
<style>
.box {
width: 200px;
height: 200px;
background-color: #42b983;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
}
/* 进入过渡 */
.fade-enter-from {
opacity: 0;
transform: scale(0.5);
}
.fade-enter-active {
transition: all 0.3s ease;
}
.fade-enter-to {
opacity: 1;
transform: scale(1);
}
/* 离开过渡 */
.fade-leave-from {
opacity: 1;
transform: scale(1);
}
.fade-leave-active {
transition: all 0.3s ease;
}
.fade-leave-to {
opacity: 0;
transform: scale(0.5);
}
</style>3.2 CSS动画效果
CSS动画与CSS过渡类似,但动画是通过@keyframes定义的:
<template>
<div>
<button @click="show = !show">Toggle Animation</button>
<transition name="bounce">
<div v-if="show" class="box">
Hello Animation
</div>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
show: true
}
}
}
</script>
<style>
.box {
width: 200px;
height: 200px;
background-color: #3498db;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
}
/* 进入动画 */
.bounce-enter-active {
animation: bounce-in 0.5s;
}
/* 离开动画 */
.bounce-leave-active {
animation: bounce-in 0.5s reverse;
}
/* 定义动画 */
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
</style>4. 自定义过渡类名
Vue允许我们通过自定义过渡类名,使用第三方CSS动画库(如Animate.css):
4.1 使用自定义类名
<template>
<div>
<button @click="show = !show">Toggle Animate.css</button>
<transition
enter-active-class="animate__animated animate__fadeIn"
leave-active-class="animate__animated animate__fadeOut"
>
<div v-if="show" class="box">
Hello Animate.css
</div>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
show: true
}
}
}
</script>
<style>
/* 引入Animate.css */
@import 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css';
.box {
width: 200px;
height: 200px;
background-color: #e74c3c;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
}
</style>4.2 所有自定义类名
| 属性名 | 描述 |
|---|---|
enter-from-class |
自定义进入起始类名 |
enter-active-class |
自定义进入激活类名 |
enter-to-class |
自定义进入结束类名 |
leave-from-class |
自定义离开起始类名 |
leave-active-class |
自定义离开激活类名 |
leave-to-class |
自定义离开结束类名 |
5. 过渡动画的配置选项
5.1 持续时间
可以通过duration属性设置过渡的持续时间:
<template>
<div>
<transition name="fade" :duration="1000">
<div v-if="show" class="box">
Slow Transition
</div>
</transition>
<!-- 分别设置进入和离开的持续时间 -->
<transition name="fade" :duration="{ enter: 500, leave: 800 }">
<div v-if="show" class="box">
Different Durations
</div>
</transition>
</div>
</template>5.2 过渡模式
默认情况下,进入和离开动画会同时进行。可以通过mode属性设置过渡模式:
- **
in-out**:新元素先进入,旧元素再离开 - **
out-in**:旧元素先离开,新元素再进入
<template>
<div>
<button @click="view = view === 'A' ? 'B' : 'A'">
Toggle View
</button>
<transition name="fade" mode="out-in">
<component :is="view" key="view"></component>
</transition>
</div>
</template>
<script>
const ComponentA = { template: '<div class="box">Component A</div>' }
const ComponentB = { template: '<div class="box">Component B</div>' }
export default {
components: {
ComponentA,
ComponentB
},
data() {
return {
view: 'A'
}
}
}
</script>5.3 动画结束的检测
Vue会自动检测过渡或动画的结束,但在某些情况下(如使用JavaScript动画库),可能需要手动触发结束事件:
<template>
<div>
<transition
name="custom"
@before-enter="beforeEnter"
@enter="enter"
@leave="leave"
:css="false"
>
<div v-if="show" class="box">
JavaScript Animation
</div>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
show: true
}
},
methods: {
beforeEnter(el) {
el.style.opacity = 0
el.style.transform = 'translateX(-100px)'
},
enter(el, done) {
// 使用GSAP等动画库
// gsap.to(el, { opacity: 1, x: 0, duration: 0.5, onComplete: done })
// 手动实现动画
let opacity = 0
let x = -100
const step = () => {
opacity += 0.05
x += 5
el.style.opacity = opacity
el.style.transform = `translateX(${x}px)`
if (opacity < 1) {
requestAnimationFrame(step)
} else {
done() // 必须调用done()通知Vue动画结束
}
}
requestAnimationFrame(step)
},
leave(el, done) {
// 离开动画逻辑
done()
}
}
}
</script>6. 不同类型的过渡
6.1 单个元素的过渡
最基本的过渡用法,用于单个元素的显示和隐藏:
<transition name="fade">
<div v-if="show" class="box">Single Element</div>
</transition>6.2 动态组件的过渡
用于动态组件的切换:
<transition name="fade" mode="out-in">
<component :is="currentComponent" key="currentComponent"></component>
</transition>6.3 条件渲染的过渡
用于v-if/v-else/v-else-if的条件渲染:
<transition name="fade">
<div v-if="condition" class="box">A</div>
<div v-else class="box">B</div>
</transition>6.4 事件驱动的过渡
用于事件触发的过渡效果:
<transition name="shake" appear>
<div class="box" @click="shake = !shake" :key="shake">
Click to Shake
</div>
</transition>7. 过渡动画的最佳实践
7.1 性能优化
- 使用CSS过渡和动画:优先使用CSS过渡和动画,避免使用JavaScript动画
- 使用transform和opacity:这两个属性的过渡不会触发重排,性能更好
- 避免使用display属性:display属性的切换会导致过渡效果失效
- 使用will-change:对于复杂的动画,可以使用will-change属性提示浏览器优化
7.2 动画设计原则
- 简洁明了:动画效果应简洁,避免过度使用
- 有意义:动画应增强用户体验,而不是分散注意力
- 一致的风格:整个应用的动画风格应保持一致
- 适当的持续时间:动画持续时间应适中,一般在200-500ms之间
7.3 可访问性考虑
- 提供关闭动画的选项:为用户提供关闭动画的选项,尤其是对于有前庭障碍的用户
- 使用prefers-reduced-motion媒体查询:检测用户是否偏好减少动画
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}7.4 调试技巧
- 使用浏览器开发者工具:观察类名的添加和移除
- 添加过渡延迟:便于观察过渡的各个阶段
- 使用appear属性:使元素初始渲染时也应用过渡效果
- 检查CSS选择器:确保过渡类名的选择器优先级正确
8. 常见问题与解决方案
8.1 过渡效果不生效
问题:元素显示/隐藏时没有过渡效果
解决方案:
- 检查是否包裹了
<transition>组件 - 检查name属性是否正确
- 检查CSS类名是否与name属性匹配
- 检查元素是否有唯一的key属性
- 检查是否使用了v-if/v-show指令
8.2 过渡效果闪烁
问题:元素在过渡过程中出现闪烁
解决方案:
- 确保enter-from和leave-to状态设置了正确的初始值
- 避免使用display属性,可以使用visibility属性替代
- 添加backface-visibility: hidden属性
8.3 多个元素同时过渡
问题:多个元素的过渡效果相互影响
解决方案:
- 为每个元素添加唯一的key属性
- 使用mode属性控制过渡顺序
- 为不同元素使用不同的过渡名称
8.4 过渡结束后样式残留
问题:过渡结束后,某些样式仍然残留
解决方案:
- 确保过渡类名的样式只在过渡期间生效
- 使用!important覆盖默认样式
- 检查是否有其他CSS规则影响过渡效果
9. 综合示例
9.1 卡片翻转效果
<template>
<div class="card-container">
<transition name="flip" mode="out-in">
<div
class="card"
:class="{ flipped: isFlipped }"
@click="isFlipped = !isFlipped"
key="isFlipped"
>
<div class="card-front">
<h2>Card Front</h2>
<p>Click to flip</p>
</div>
<div class="card-back">
<h2>Card Back</h2>
<p>Hello from the other side!</p>
</div>
</div>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
isFlipped: false
}
}
}
</script>
<style>
.card-container {
perspective: 1000px;
width: 300px;
height: 200px;
margin: 50px auto;
}
.card {
position: relative;
width: 100%;
height: 100%;
transform-style: preserve-3d;
transition: transform 0.6s;
}
.card-front,
.card-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
border-radius: 10px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: white;
font-size: 18px;
}
.card-front {
background-color: #42b983;
}
.card-back {
background-color: #3498db;
transform: rotateY(180deg);
}
/* 翻转过渡 */
.flip-enter-from {
transform: rotateY(180deg);
}
.flip-enter-active {
transition: transform 0.6s;
}
.flip-enter-to {
transform: rotateY(0deg);
}
.flip-leave-from {
transform: rotateY(0deg);
}
.flip-leave-active {
transition: transform 0.6s;
}
.flip-leave-to {
transform: rotateY(180deg);
}
</style>9.2 模态框过渡效果
<template>
<div>
<button @click="showModal = true">Open Modal</button>
<transition name="modal">
<div v-if="showModal" class="modal-overlay" @click="showModal = false">
<transition name="modal-content">
<div class="modal-content" @click.stop>
<h2>Modal Title</h2>
<p>This is a modal dialog with transition effects.</p>
<button @click="showModal = false">Close</button>
</div>
</transition>
</div>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
showModal: false
}
}
}
</script>
<style>
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal-content {
background-color: white;
padding: 30px;
border-radius: 8px;
max-width: 500px;
width: 100%;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
}
/* 遮罩层过渡 */
.modal-enter-from {
opacity: 0;
}
.modal-enter-active {
transition: opacity 0.3s ease;
}
.modal-enter-to {
opacity: 1;
}
.modal-leave-from {
opacity: 1;
}
.modal-leave-active {
transition: opacity 0.3s ease;
}
.modal-leave-to {
opacity: 0;
}
/* 内容过渡 */
.modal-content-enter-from {
opacity: 0;
transform: scale(0.8) translateY(-50px);
}
.modal-content-enter-active {
transition: all 0.3s ease;
}
.modal-content-enter-to {
opacity: 1;
transform: scale(1) translateY(0);
}
.modal-content-leave-from {
opacity: 1;
transform: scale(1) translateY(0);
}
.modal-content-leave-active {
transition: all 0.3s ease;
}
.modal-content-leave-to {
opacity: 0;
transform: scale(0.8) translateY(-50px);
}
</style>10. 总结
Vue的过渡系统基于CSS类名的切换,提供了强大的过渡动画能力。通过理解过渡动画的基础类名和生命周期,我们可以创建各种平滑的过渡效果。
主要知识点:
- 过渡动画的基础类名:enter-from、enter-active、enter-to、leave-from、leave-active、leave-to
- 过渡动画的生命周期:进入过渡和离开过渡的各个阶段
- 自定义过渡类名:支持使用第三方CSS动画库
- 过渡动画的配置选项:duration、mode、css等
- 不同类型的过渡:单个元素、动态组件、条件渲染等
- 过渡动画的最佳实践:性能优化、可访问性考虑等
过渡动画是提升用户体验的重要手段,合理使用过渡动画可以使应用更加生动和友好。但也要注意不要过度使用,避免影响应用的性能和可用性。
11. 练习
- 使用基本过渡类名创建一个淡入淡出效果
- 使用CSS动画创建一个弹跳效果
- 结合Animate.css创建复杂的过渡效果
- 实现一个卡片翻转的3D过渡效果
- 实现一个模态框的过渡效果
- 为路由切换添加过渡动画