Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡
- 条件渲染 (使用 v-if)
- 条件展示 (使用 v-show)
- 动态组件
- 组件根节点
8.1 使用过渡类名实现动画
一个完整的动画分为了两部分:进入部分和离开部分;
进入和离开部分都分为两个时间点和一个时间段;
8.1.1、进入部分
v-enter:
动画进入之前元素的初始状态。
在元素被插入之前生效,在元素被插入之后的下一帧移除。
v-enter-to:
动画进入完成之后的借宿状态;
在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。
v-enter-active:
进入动画的时间段。
在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
8.1.2、离开部分
v-leave:
动画离开之前元素的初始状态;
在离开过渡被触发时立刻生效,下一帧被移除。
v-leave-to:
动画离开完成之后的借宿状态;
在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。
v-leave-active:
离开动画的时间段;
在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
其中:
v-enter 和 v-leave-to的状态是一致的;
v-enter-to和 v-leave 的状态是一致的;
8.1.3、元素的过渡步骤
- 使用transition元素,把 需要被动画控制的元素 包裹起来;
- 自定义两组样式,来控制 transition 内部元素实现动画;
<button @click="flag=!flag">显示/隐藏</button>
<transition>
<p v-show="flag">我想通过动画显示隐藏</p>
</transition>
<script>
new Vue({
data:{
flag: true;
}
})
</script>
<style>
.v-enter,
.v-leave-to {
opacity: 0;
}
.v-leave-active,
.v-enter-active {
transition: all 0.4s;
}
</style>
8.2 自定义过渡类名
8.2.1 步骤
- 在 transition 标签上添加name属性,并给name属性赋值,赋的值替换 ‘v-’ 来作为过渡类类名的前缀;
- 使用自定义过渡类名 定义两组样式,来控制 transition 内部元素实现动画;
<button @click="flag=!flag">显示/隐藏</button>
<transition name='my'>
<p v-show="flag">我想通过动画显示隐藏</p>
</transition>
<script>
new Vue({
data:{
flag: true;
}
})
</script>
<style>
.my-enter,
.my-leave-to {
opacity: 0;
}
.my-leave-active,
.my-enter-active {
transition: all 0.4s;
}
</style>
8.3 钩子函数实现动画
使用过渡类名和使用第三方的库来实现动画,都不能实现半场动画,有时候我们只需要半场,不需要整场动画(比如加入购物车动画),只能借助于钩子函数来实现。
钩子函数页可以说是动画的生命周期函数:
入场的钩子函数
<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>
当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则,它们将被同步调用,过渡会立即完成。
methods: {
// --------
// 进入中
// --------
beforeEnter: function (el) {
// ...
},
// 当与 CSS 结合使用时
// 回调函数 done 是可选的
enter: function (el, done) {//此时的done其实就是afterEnter函数的引用
// ... // 当需要的操作完成之后,就会自动去调用done(),也就是立即调用 afterEnter函数;
done()
},
afterEnter: function (el) {
// ...
},
enterCancelled: function (el) {
// ...
},
8.4 列表过渡
8.4.1 transition-group
在实现列表过渡的时候,如果需要过渡的元素是通过 v-for 循环渲染出来,不能使用 transition 包裹,需要使用 <transition-group>
特点:
- 不同于 <transition>,它会以一个真实元素呈现:默认为一个 <span>。你也可以通过 tag 特性更换为其他元素。
- 过渡模式不可用,因为我们不再相互切换特有的元素。
- 内部元素 总是需要 提供唯一的 key 属性值。
- CSS 过渡的类将会应用在内部的元素中,而不是这个组/容器本身。
具体案例可以看官方文档,说的比较详细。
8.4.2 appear
给transition-group添加 appear
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="./lib/vue-2.4.0.js"></script>
<link rel="stylesheet" href="./lib/bootstrap-3.3.7.css">
<style>
#app {
padding: 100px 0;
}
li {
width: 100%;
}
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateY(100px);
}
.v-enter-active,
.v-leave-active {
transition: all 1s ease;
}
/* 可以设置元素在位移的时候的过渡效果 */
/* v-move和v-leave-active 配合使用 可以实现列表后续的元素渐渐飘上来的效果 */
.v-move {
transition: all 1s;
}
.v-leave-active {
position: absolute;
}
</style>
</head>
<body>
<div id="app" class="container">
<label for="">
id:
<input type="text" v-model="id">
</label>
<label for="">
name:
<input type="text" v-model="name" @keyup.enter="add()">
</label>
<input type="button" class="btn btn-default primary" @click="add()" value="添加">
<!-- <ul class="list-group"> -->
<!-- 在实现过渡列表的时候 我们要使用 transitionGroup -->
<!-- 如果要为v-for 的元素设置 -->
<!-- 在实现列表过渡的时候 如果需要过渡的元素 是通过v-for循环出来的 不能使用transition包裹 需要使用transitionGroup包裹 -->
<!-- 如果要为v-for循环创建的元素设置动画 必须为每一个元素设置 :key属性 -->
<!-- 通过 为 transition-group 元素,设置 tag 属性,指定 transition-group 渲染为指定的元素,如果不指定 tag 属性,默认,渲染为 span 标签 -->
<!-- appear 可以实现页面入场时候的效果 -->
<transition-group appear tag="ul">
<li class="list-group-item" v-for="(item,i) in list" :key="item.id" @click="del(i)">
{{item.id}}==={{item.name}}
</li>
</transition-group>
<!-- </ul> -->
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
id: '',
name: '',
list: [{
id: 1,
name: '张三'
}, {
id: 2,
name: '李四'
}, {
id: 3,
name: '王五'
}]
},
methods: {
add() {
this.list.push({
id: this.id,
name: this.name
})
},
del(i) {
this.list.splice(i, 1)
}
}
})
</script>
</body>
</html>