过渡的要点:
- 需要进行动画的元素外面要加一个<transition>标签
- 需要进行动画的元素必须使用v-if或v-show
- 进入动画就是一个元素从没有到有的过程,如果一开始这个元素不显示那么执行的就是进入动画
- 离开动画就是一个元素从有到没有的过程,如果一开始这个元素显示,那么执行的就是离开动画
- 多个相同标签的元素做动画,需要给每一个标签加一个key里面是唯一值
- -enter-to(进入结束)和-leave(离开之前)一般不需要写,因为他们都是默认状态
- 对于css过渡
-enter
和-leave-to
是一样的状态,-enter-active
和-leave-active
也是一样的状态,所以他们可以两两合写在一起
比如:
.fade-enter-active, .fade-leave-active{ transition: all 1s; }
.fade-enter, .fade-leave-to{ opacity: 0; }
- 对于animation只需要使用
-enter-active
和-leave-active
然后分别引入同一个动画,只不过离开的时候将这个动画reverse一下
进入动画(enter)
进入之前:-enter
进入结束:-enter-to
image.png
离开动画(leave)
image.png通过@transitionend来执行过渡完成后的方法
如果想让一个动画每次滚动回来都执行的话,那么就要使用过渡提供的js钩子
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
v-on:enter-cancelled="enterCancelled"
v-on:before-leave="beforeLeave"
v-on:leave="leave"
v-on:after-leave="afterLeave"
v-on:leave-cancelled="leaveCancelled"
>
<!-- ... -->
</transition>
// ...
methods: {
// --------
// 进入中
// --------
beforeEnter: function (el) {
// ...
},
// 当与 CSS 结合使用时
// 回调函数 done 是可选的
enter: function (el, done) {
// ...
done()
},
afterEnter: function (el) {
// ...
},
enterCancelled: function (el) {
// ...
},
// --------
// 离开时
// --------
beforeLeave: function (el) {
// ...
},
// 当与 CSS 结合使用时
// 回调函数 done 是可选的
leave: function (el, done) {
// ...
done()
},
afterLeave: function (el) {
// ...
},
// leaveCancelled 只用于 v-show 中
leaveCancelled: function (el) {
// ...
}
}
一个案例:
封装一个fullpage组件,里面使用transition-group,需要监听每次进去当前页面和离开,所以只需用到enter和leave钩子,然后在data里声明一个state初始值是'',当enter钩子执行时state的值就是enter,leave就是leave,然后将这个state传到slot插槽上,这样其它的组件可以直接在fullpage的作用域下得到它的state了,如下
fullpage.vue
<template>
<transition-group tag="div" :name="name"
@enter="enter"
@leave="leave"
>
<div v-for="(list,index) in 5" v-show="index === 1" @transitionend="end"></div>
<slot :state="state"></slot>
</transition-group>
</template>
<script>
export default{
data(){
return {
state: ''
}
},
methods: {
enter(el,done){
this.state = 'enter'
},
leave(el,done){
this.state = 'leave'
},
end(){
this.state = 'transitionend'
}
}
}
</script>
这时候如果另外有一个组件有动画效果或内容要加在这个fullpage组件上,就通过slot来使用,下面将另一个组件命名为page1
index.html
<div id="app">
<Fullpage>
//这里通过slot-scope将组件的作用域绑定到Fullpage上,只要下面通过prop.访问的都是组件内的数据
<template slot-scope="prop">
<page1 :state="prop.state"></page1>
</template>
</Fullpage>
</div>
然后只要在page1组件里的props传入这个state就可以拿到了,之后就在page1组件里使用watch监听state,如果是state是enter就执行动画,否则就移除
page1.vue
export default{
props: ['state'],
watch: {
state(){
if(this.state=== 'enter'){
//要执行的动画
}else{
//结束动画
}
}
}
}
css animation的使用
- 自定义animation
- 只需要写enter-active和leave-active就行
- 定义的animation动画结束的时候一定要是正常状态
- 进入和离开只需要用同一个动画,只不过有一个是相反就行
比如:
<style>
.bounce-enter-active {
animation: bounce-in .5s;
}
.bounce-leave-active {
animation: bounce-in .5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
</style>
<div id="example-2">
<button @click="show = !show">Toggle show</button>
<transition name="bounce">
<p v-if="show">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris facilisis enim libero, at lacinia diam fermentum id. Pellentesque habitant morbi tristique senectus et netus.</p>
</transition>
</div>
<script>
new Vue({
el: '#example-2',
data: {
show: true
}
})
</script>
- 使用第三方库
只需要在transition标签里使用enter-acitve-class和leave-active-class指定它们使用的库里面的类名就行
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
<div id="example-3">
<button @click="show = !show">
Toggle render
</button>
<transition
enter-active-class="animated tada"
leave-active-class="animated bounceOutRight"
>
<p v-if="show">hello</p>
</transition>
</div>
多个元素的过渡
注意:
1.如果有相同标签名的元素切换时,需要通过key设置唯一的值区分
2.旧元素的离开和新元素的进入动画会同时执行,所以我们需要给<transition>
标签加一个mode
in-out:新元素先进行过渡,完成之后当前元素过渡离开。
out-in:当前元素先进行过渡,完成之后新元素过渡进入。
<style>
.fade-enter-active,.fade-leave-active{
transition: all .3s linear;
}
.fade-enter{
opacity: 0;
}
.fade-leave-to{
opacity: 0;
}
</style>
<div id="app">
<transition name="fade" mode="out-in">
<button v-if="status === 'out'" @click="status='in'" key="out">out</button>
<button v-else @click="status = 'out'" key="in">in</button>
</transition>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
status: 'out'
}
})
</script>
多个组件的过渡
通过给component标签外加transition标签,然后给component加一个动态is属性,通过is绑定的属性更改组件
<div id="app">
<button @click="view='v-a'">A</button>
<button @click="view='v-b'">B</button>
<transition name="fade" mode="out-in">
<component :is="view"></component>
</transition>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
view: 'v-a'
},
components: {
'v-a': {
template: '<div>Component A</div>'
},
'v-b': {
template: '<div>Component B</div>'
}
}
})
</script>
列表过渡
- 需要过渡的外层使用<transition-group>,它默认会显示为span标签,你也可以通过 tag 特性更换为其他元素。
- 不可以使用mode
- 必须绑定key
- transition-troup标签内必须紧跟for循环
<style>
.list-item {
display: block;
margin-right: 10px;
}
.list-enter-active, .list-leave-active {
transition: all 1s;
}
.list-enter, .list-leave-to
{
opacity: 0;
transform: translateX(90%);
</style>
<div id="list-demo" class="demo">
<button v-on:click="add">Add</button>
<button v-on:click="remove">Remove</button>
<transition-group name="list" tag="p">
<span v-for="item in items" v-bind:key="item" class="list-item">
{{ item }}
</span>
</transition-group>
</div>
<script>
new Vue({
el: '#list-demo',
data: {
items: [1,2,3,4,5,6,7,8,9],
nextNum: 10
},
methods: {
randomIndex: function () {
return Math.floor(Math.random() * this.items.length)
},
add: function () {
this.items.splice(this.randomIndex(), 0, this.nextNum++)
},
remove: function () {
this.items.splice(this.randomIndex(), 1)
},
}
})
</script>
网友评论