12-Vue2 过渡与动画
Vue2 过渡与动画
过渡和动画让应用的交互更加流畅自然。Vue 提供了内置的
transition和transition-group组件,配合 CSS 和 JavaScript 钩子,可以轻松实现各种进入、离开和列表过渡效果。
一、前言
在 modern web 应用中,用户体验至关重要。元素的突然出现和消失会让界面显得生硬,而恰当的过渡动画能够:
- 引导用户的注意力
- 传达状态变化(加载、成功、错误)
- 提升应用的质感与专业度
Vue 内置了一套完善的过渡系统,无需引入第三方库即可实现大多数动画需求。
二、transition 组件
2.1 基本用法
使用transition包裹需要过渡的元素或组件:
<transitionname="fade"><pv-if="show">内容</p></transition>/* 进入/离开的激活状态 */.fade-enter-active, .fade-leave-active{transition:opacity 0.5s;}/* 进入开始 / 离开结束 */.fade-enter, .fade-leave-to{opacity:0;}2.2 过渡类名详解
Vue 为过渡元素自动添加 6 个类名:
| 类名 | 说明 |
|---|---|
v-enter | 进入开始状态,元素插入前生效 |
v-enter-active | 进入整个激活状态,过渡/动画生效期间 |
v-enter-to | 进入结束状态(Vue 2.1.8+) |
v-leave | 离开开始状态 |
v-leave-active | 离开整个激活状态 |
v-leave-to | 离开结束状态(Vue 2.1.8+) |
使用name="fade"后,类名前缀v-替换为fade-。
2.3 CSS 过渡示例
<template><div><button@click="show = !show">切换</button><transitionname="slide-fade"><pv-if="show">带位移的淡入淡出</p></transition></div></template>/* 进入和离开动画 */.slide-fade-enter-active{transition:all 0.3s ease;}.slide-fade-leave-active{transition:all 0.8scubic-bezier(1,0.5,0.8,1);}/* 进入开始 / 离开结束状态 */.slide-fade-enter, .slide-fade-leave-to{transform:translateX(10px);opacity:0;}三、CSS 动画
3.1 使用 @keyframes
与 CSS 过渡的区别在于动画使用@keyframes:
<transitionname="bounce"><pv-if="show"style="display:inline-block">弹跳动画</p></transition>.bounce-enter-active{animation:bounce-in 0.5s;}.bounce-leave-active{animation:bounce-in 0.5s reverse;}@keyframesbounce-in{0%{transform:scale(0);}50%{transform:scale(1.5);}100%{transform:scale(1);}}3.2 自定义过渡类名
当需要使用第三方 CSS 动画库(如 Animate.css)时,可以自定义类名:
<transitionenter-active-class="animate__animated animate__bounceIn"leave-active-class="animate__animated animate__bounceOut"><pv-if="show">Animate.css 动画</p></transition>四、JavaScript 钩子
4.1 事件钩子函数
可以在过渡属性中声明 JavaScript 钩子:
<transition@before-enter="beforeEnter"@enter="enter"@after-enter="afterEnter"@enter-cancelled="enterCancelled"@before-leave="beforeLeave"@leave="leave"@after-leave="afterLeave"@leave-cancelled="leaveCancelled"><pv-if="show">JavaScript 控制过渡</p></transition>methods:{beforeEnter(el){el.style.opacity=0;},enter(el,done){Velocity(el,{opacity:1,fontSize:'1.4em'},{duration:300,complete:done});},afterEnter(el){console.log('进入完成');}}注意:使用 JavaScript 钩子时,需要添加:css="false"告诉 Vue 跳过 CSS 检测,避免与 JavaScript 动画冲突。
五、初始渲染过渡
5.1 appear 属性
在首次渲染时应用过渡效果:
<transitionappear><p>页面加载时自动执行进入动画</p></transition>也可以自定义 appear 类名:
<transitionappearappear-class="custom-appear-class"appear-active-class="custom-appear-active-class"><p>自定义初始动画</p></transition>六、transition-group 列表过渡
6.1 列表的进入/离开过渡
transition-group用于同时渲染多个元素的过渡:
<transition-groupname="list"tag="ul"><liv-for="item in items":key="item.id">{{ item.text }}</li></transition-group>.list-enter-active, .list-leave-active{transition:all 0.5s;}.list-enter, .list-leave-to{opacity:0;transform:translateX(30px);}6.2 列表排序过渡
为列表的排序添加平滑过渡:
<transition-groupname="flip-list"tag="ul"><liv-for="item in items":key="item.id">{{ item.text }}</li></transition-group>.flip-list-move{transition:transform 0.5s;}methods:{shuffle(){this.items=_.shuffle(this.items);}}6.3 列表的交错过渡
通过 data 属性与 CSS 变量实现交错延迟:
<transition-groupname="stagger"tag="ul"><liv-for="(item, index) in items":key="item.id":data-index="index">{{ item.text }}</li></transition-group>.stagger-enter-active, .stagger-leave-active{transition:all 0.5s;}.stagger-enter, .stagger-leave-to{opacity:0;transform:translateY(30px);}.stagger-move{transition:transform 0.5s;}/* 交错过渡 */.stagger-enter-active{transition-delay:calc(0.1s *var(--index));}七、可复用的过渡组件
将过渡封装为可复用组件:
// components/FadeTransition.vue<template><transition name="fade"mode="out-in"><slot></slot></transition></template><style scoped>.fade-enter-active,.fade-leave-active{transition:opacity0.3s ease;}.fade-enter,.fade-leave-to{opacity:0;}</style>使用:
<FadeTransition><router-view/></FadeTransition>八、过渡模式
8.1 mode 属性
当切换两个元素时,控制进入和离开的顺序:
<!-- in-out:新元素先进入,旧元素再离开 --><transitionname="fade"mode="in-out"><button:key="isEditing"@click="isEditing = !isEditing">{{ isEditing ? '保存' : '编辑' }}</button></transition><!-- out-in:旧元素先离开,新元素再进入(推荐) --><transitionname="fade"mode="out-in"><component:is="currentView"></component></transition>| 模式 | 说明 | 适用场景 |
|---|---|---|
in-out | 新元素先进入 | 较少使用,可能重叠 |
out-in | 旧元素先离开 | 推荐,避免位置重叠 |
九、第三方动画库集成
9.1 使用 GSAP
<transition@enter="enter"@leave="leave":css="false"><pv-if="show">GSAP 动画</p></transition>importgsapfrom'gsap';methods:{enter(el,done){gsap.from(el,{opacity:0,y:-50,duration:0.5,onComplete:done});},leave(el,done){gsap.to(el,{opacity:0,y:50,duration:0.5,onComplete:done});}}十、总结
| 特性 | 用途 | 关键属性/类名 |
|---|---|---|
| transition | 单元素/组件过渡 | name, mode, appear |
| 进入类 | 控制进入动画 | v-enter, v-enter-active, v-enter-to |
| 离开类 | 控制离开动画 | v-leave, v-leave-active, v-leave-to |
| transition-group | 列表过渡 | tag, move-class |
| JavaScript 钩子 | 复杂动画控制 | @enter, @leave |
| appear | 初始渲染动画 | appear, appear-class |
核心原则:优先使用 CSS 过渡(性能更好),复杂场景使用 JavaScript 钩子配合动画库。
下一章我们将学习 Vue 的渲染函数与 JSX,深入理解 Vue 的模板编译机制。
十一、练习
- 实现一个带淡入淡出效果的模态框组件
- 创建一个可排序的待办事项列表,添加/删除/排序都有平滑动画
- 使用 transition-group 实现一个图片画廊,支持添加/删除图片
- 封装一个通用的 FadeTransition 组件,用于路由切换动画