transition
transition组件可以给任何元素或组件添加进入/离开的过渡,使用情形:
- 条件渲染(v-if)
- 条件展示(v-show)
- 动态组件
- 组件根节点
类名
默认类名
在进入/离开的过渡中,会有6个class切换:
- v-enter-from:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
- v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。常用来定义进入过渡的过程时间,延迟和曲线函数。
- v-enter-to:定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时v-enter-from被移除),在过渡/动画完成之后移除。
- v-leave-from:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
- v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。常用来定义离开过渡的过程时间,延迟和曲线函数。
- v-leave-to:离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时v-leave-from被移除),在过渡/动画完成之后移除。
为transition组件添加name属性,并在css中把上述类名的v替换成name属性值,再写入对应样式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| <template> <div class="container"> <button @click="flag = !flag">switch</button> <transition name="fade"> <div v-if="flag" class="box"></div> </transition> </div> </template>
<script setup lang="ts"> import { ref } from "vue"
const flag = ref<boolean>(true) </script>
<style lang="scss"> .box { width: 200px; height: 200px; background-color: pink; } // 进入前的状态 .fade-enter-from { width: 0; height: 0; transform: rotate(360deg); } // 进入时的过渡 .fade-enter-active { transition: all 1s ease; } // 进入结束的状态 .fade-enter-to { // 最好和本身的样式保持一致 width: 200px; height: 200px; } // 退出前的状态 .fade-leave-from { width: 200px; height: 200px; transform: rotate(360deg); } // 退出时的过渡 .fade-leave-active { transition: all 1s ease; } // 退出结束的状态 .fade-leave-to { width: 0; height: 0; } </style>
|
自定义类名
为transition传prop:
- enter-from-class
- enter-active-class
- enter-to-class
- leave-from-class
- leave-active-class
- leave-to-class
例如设enter-from-class为”abc”,就能通过类名abc规定对应的动画过程了。
这样做更方便样式的复用,或结合第三方类库使用。
1 2 3 4 5 6 7 8 9 10 11 12
| <transition enter-from-class="abc" name="fade"> <div v-if="flag" class="box"></div> </transition>
// 省略......
<style> // 进入前的状态 .abc { // 省略...... } </style>
|
结合Animate.css
自定义类名结合Animate.css动画库使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| <template> <div class="container"> <button @click="flag = !flag">switch</button> <!-- duration:动画执行时间 --> <!-- 传入一个数字,则进入和离开都遵循此时间(例 :duration="500") --> <!-- 传入一个对象,则可对进入和离开单独定义(例 :duration="{enter:250,leave:500}") --> <transition leave-active-class="animate__animated animate__fadeOut" enter-active-class="animate__animated animate__fadeIn" :duration="{enter:250,leave:500}"> <div v-if="flag" class="box"></div> </transition> </div> </template>
<script setup lang="ts"> import { ref } from "vue" import "animate.css"
const flag = ref<boolean>(true) </script>
<style lang="scss"> .box { width: 200px; height: 200px; background-color: pink; } </style>
|
生命周期
transition有八个生命周期:
@before-enter="beforeEnter"
:对应enter-from@enter="enter"
:对应enter-active@after-enter="afterEnter"
:对应enter-to@enter-cancelled="enterCancelled"
:显示过度打断@before-leave="beforeLeave"
:对应leave-from@leave="leave"
:对应enter-active@after-leave="afterLeave"
:对应leave-to@leave-cancelled="leaveCancelled"
:离开过度打断
因为有一些复杂的过渡效果无法被CSS实现,必须动用JS,所以Vue提供了transition的生命周期。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| <template> <div class="container"> <button @click="flag = !flag">switch</button> <!-- duration:动画执行时间 --> <!-- 传入一个数字,则进入和离开都遵循此时间(例 :duration="500") --> <!-- 传入一个对象,则可对进入和离开单独定义(例 :duration="{enter:250,leave:500}") --> <transition @before-enter="EnterFrom" @enter="EnterActive" @after-enter="EnterTo" @enter-cancelled="EnterCancel" @before-leave="LeaveFrom" @leave="LeaveActive" @after-leave="LeaveTo" @@leave-cancelled="LeaveCancel"> <div v-if="flag" class="box"></div> </transition> </div> </template>
<script setup lang="ts"> import { ref } from "vue" import "animate.css"
const flag = ref<boolean>(true)
// @param el 被过渡的元素 const EnterFrom = (el: Element)=> { console.log("进入前") } // @param done 完成时执行的回调 const EnterActive = (el: Element, done: Function)=> { console.log("进入时") // 进入动画三秒后完成 setTimeout(() => { done() }, 3000) } const EnterTo = (el: Element)=> { console.log("进入完") } const EnterCancel = (el: Element)=> { console.log("打断进入") }
const LeaveFrom = (el: Element)=> { console.log("离开前") } const LeaveActive = (el: Element, done: Function)=> { console.log("离开时") // 离开动画三秒后完成 setTimeout(() => { done() }, 3000) } const LeaveTo = (el: Element)=> { console.log("离开完") } const LeaveCancel = (el: Element)=> { console.log("打断离开") } </script>
<style lang="scss"> .box { width: 200px; height: 200px; background-color: pink; } </style>
|
结合GSAP
GSAP是一个JS动画库,可以结合transition组件的生命周期使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| <template> <div class="container"> <button @click="flag = !flag">switch</button> <transition @before-enter="EnterFrom" @enter="EnterActive" @leave="LeaveActive"> <div v-if="flag" class="box"></div> </transition> </div> </template>
<script setup lang="ts"> import { ref } from "vue" import gsap from "gsap"
const flag = ref<boolean>(true)
const EnterFrom = (el: Element)=> { gsap.set(el, { width:0, height:0 }) } const EnterActive = (el: Element, done: gsap.Callback)=> { gsap.to(el, { width:200, height:200, onComplete:done }) } const LeaveActive = (el: Element, done: gsap.Callback)=> { gsap.to(el, { width:0, height:0, onComplete:done }) } </script>
<style lang="scss"> .box { width: 200px; height: 200px; background-color: pink; } </style>
|
appear
appear有三个属性:
- appear-from-class
- appear-active-class
- appear-to-class
通过这些属性可以设置初始节点过渡,即页面加载完成就开始的动画。
但进入或离开的时候不会执行这些动画。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| <template> <div class="container"> <button @click="flag = !flag">switch</button> <transition appear appear-from-class="from" appear-active-class="active" appear-to-class="to"> <div v-if="flag" class="box"></div> </transition> </div> </template>
<script setup lang="ts"> import { ref } from "vue"
const flag = ref<boolean>(true) </script>
<style lang="scss"> .box { width: 200px; height: 200px; background-color: pink; } .from { width: 0px; height: 0px; } .active { transition: all 1s ease; } .to { width: 200px; height: 200px; } </style>
|