transition
vue允许我们在显示隐藏元素以及创建元素过程中,添加过渡效果
transition元素(组件)是由vue提供的,可以为内部的元素添加过渡效果
过程演示
v-enter:过渡的初始状态(隐藏);在过渡开始前被添加,在过渡开始时会被移除
v-enter-to:过渡的结束状态(显示);在过渡开始时被添加,在过渡完成时会被移除
v-enter-active:这里包含了上面的v-enter、v-enter-to两个时间段,在这里可以对上半场过渡定义过渡时间、曲线等
v-leave:过渡的初始状态(显示);在过渡开始前被添加,在过渡开始时会被移除
v-leave-to:过渡的结束状态(隐藏);在过渡开始时被添加,在过渡完成时会被移除
v-leave-active:这里包含了上面的v-leave、v-leave-to两个时间段,在这里可以对下半场过渡定义过渡时间、曲线等
通过name属性设置过渡名称,之后就会根据该名称创建六个类
例如name = ‘demo’
表示显示的过程(由隐藏的状态变成显示的状态)
.demo-enter .demo-enter-to .demo-enter-active
表示隐藏的过程(由显示状态变成隐藏的状态)
.demo-leave .demo-leave-to .demo-leave-active
transition组件只是加了这六各类,具体的效果还需要通过css过渡或者动画(借助css3实现的)
入场过渡
我们通过为transition组件添加appear属性,实现入场过渡:当元素加载的时候,执行动画
- 通过动画效果实现
html
<div id="app">
<button @click="toggle">切换</button>
<!-- 通过name定义名称,这个名字可以自己取 -->
<transition name="demo">
<div class="box" v-show="isShow"></div>
</transition>
</div>
js
let app = new Vue({
el: '#app',
data: {
isShow: true
},
methods: {
toggle() {
this.isShow = !this.isShow
}
},
})
scss
.box {
width: 200px;
height: 200px;
background-color: green;
}
// 定义动画
@keyframes toggle {
// 只有两个状态,可以写0%-100%,也可以写from-to
from {
width: 200px;
height: 200px;
opacity: 1;
}
to {
width: 0;
height: 0;
opacity: 0;
}
}
// 隐藏过程设置动画,demo表示transition的name属性名称
.demo-leave-active {
// toggle表示动画名称
animation: toggle 1s;
}
// 显示过程设置动画
.demo-enter-active {
// reverse 表示动画反转,从后往前
animation: toggle 1s reverse;
}
此时会有一个动态的切换效果
- 通过过渡实现
scss
.box {
width: 200px;
height: 200px;
background-color: green;
}
// 过渡
// 隐藏
// v-enter和v-leave-to都表示隐藏的状态
.demo-enter,
.demo-leave-to {
width: 0;
height: 0;
opacity: 0;
}
// v-enter-to和v-leave都表示显示的状态
// 如果.box已经有了一个样式,有了宽度和高度,那么这个显示的类就可以 不用设置了
//.demo-enter-to,
//.demo-leave {
// width: 200px;
// height: 200px;
// opacity: 1;
//}
// 给过程添加过渡
.demo-enter-active,
.demo-leave-active {
transition: all 1s;
}
- 入场过渡
我们通过为transition组件添加appear属性,实现入场过渡:当元素加载的时候,执行动画
<div id="app">
<button @click="toggle">切换</button>
<!-- 通过name定义名称 -->
<!-- 我们通过为transition组件添加appear属性,实现入场过渡:当元素加载的时候,执行动画 -->
<transition
name="demo"
appear
>
<div class="box" v-show="isShow"></div>
</transition>
</div>
此时页面刚打开的时候就会执行动画
过渡事件
css3过渡和动画有事件,我们可以通过DOM监听到
过渡事件:webkitTransitionStart, webkitTransitionEnd
动画事件:webkitAnimationStart, webkitAnimationEnd
vue实现的过渡也可以监听动画开始与结束的事件
显示过程:
before-enter:处于隐藏状态 after-enter:处于显示状态 enter:显示过程
隐藏过程:
before-leave:处于显示状态 after-leave:处于隐藏状态 leave:隐藏过程
我们可以通过v-on指令或者是@语法糖来监听这些事件
<transition
name="demo"
appear
@before-enter="beforeEnter"
@after-enter="afterEnter"
@enter="enter"
@before-leave="beforeLeave"
@after-leave="afterLeave"
@leave="leave"
>
<div class="box" v-show="isShow"></div>
</transition>
// 事件回调函数
beforeEnter() {
console.log(111, 'beforeEnter');
},
afterEnter() {
console.log(222, 'afterEnter');
},
enter() {
console.log(333, 'enter');
},
beforeLeave() {
console.log(444, 'beforeLeave');
},
afterLeave() {
console.log(555, 'afterLeave');
},
leave() {
console.log(666, 'leave');
}
多元素过渡
我们可以在transition中,定义多个元素,实现多个元素之间的过渡
内部的元素必须设置key属性,属性值是唯一的。
我们通过mode属性定义切换模式:
in-out 新元素先执行,再执行当前的元素
out-in 当前的元素先执行,再执行新元素
默认两个元素同时执行
<!-- 我们通过mode属性定义切换模式:默认同时执行 -->
<!-- in-out 新元素先执行,再执行当前的元素
out-in 当前的元素先执行,再执行新元素 -->
<transition
name="demo"
appear
mode="in-out"
>
<div class="box" v-if="isShow" :key="1"></div>
// transition里只能有一个元素,所以必须借助v-if v-else
<div class="box2" v-else :key="2"></div>
</transition>
列表过渡
我们通过v-for指令渲染列表
使用v-for指令创建列表元素的时候,如果需要过渡,要使用transition-group组件
与transition组件的区别是:transition-group会渲染一个真实的元素
默认是span。通过tag属性可以自定义渲染的结果
使用列表过渡的时候,每一个元素都要添加一个值是唯一的并且稳定的key属性
transition与transition-group的区别
transition 控制一个元素
transition-group 控制多个元素
html
<div id="app">
<button @click="addItem">添加成员</button>
<button @click="random">打乱顺序</button>
<hr>
<transition-group name="ickt" tag="div" class="list">
<span v-for="(item, index) in nums" :key="index">{{item}}</span>
</transition-group>
</div>
css
.list {
span {
font-size: 30px;
padding: 30px 20px;
display: inline-block;
transition: all 1s;
}
}
js
let app = new Vue({
// 视图
el: '#app',
// 数据
data: {
nums: [0, 1, 2, 3, 4, 5]
},
methods: {
addItem() {
// 随机一个位置添加
this.nums.splice(
// 随机一个位置
Math.floor(Math.random() * this.nums.length),
0,
this.nums.length
)
},
// 改变数据顺序
random() {
this.nums.sort((a, b) => Math.random() < 0.5 ? 1 : -1)
}
},
})