CSS 过渡和动画
transition
常用的过渡是 CSS 过渡,使用 fade
<template>
<div id="app">
<button @click="Toggle">Toggle</button>
<transition name="fade">
<p v-if="visible">test</p>
</transition>
</div>
</template>
<script>
export default {
data(){
return{
visible:false
}
},
methods:{
Toggle(){
this.visible=!this.visible
}
}
};
</script>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .25s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
效果
从上面例子中可以看出来,当用户点击按钮时,Vue 会给目标元素插入一个CSS类名,当动画完成时,会删除这个类名,
过渡类名
- v-enter:进入过渡
- v-enter-active:过渡生效时,这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数
- v-enter-to:过渡的结束状态
- v-leave:离开过渡开始时
- v-leave-active:离开过渡生效时,这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数
- v-leave-to:离开过渡结束时
animation
<template>
<div id="app">
<button @click="Toggle">Toggle</button>
<transition name="fade">
<p v-if="visible">test</p>
</transition>
</div>
</template>
<script>
export default {
data(){
return{
visible:false
}
},
methods:{
Toggle(){
this.visible=!this.visible
}
}
};
<style>
@keyframes bounce-in{
0%{
transform: scale(0)
}
50%{
transform: scale(1.2)
}
100%{
transform: scale(1)
}
}
.bounce-enter-active{
animation: bounce-in .25s
}
.bounce-leave-active {
animation: bounce-in .25s reverse
}
</style>
效果
与transition 不同的是animation在v-enter类名在节点插入DOM后不会立即删除,而是在 animationend事件触发时删除。
自定义过渡的类名
我们可以通过以下 attribute 来自定义过渡类名:
- enter-class
- enter-active-class
- enter-to-class
- leave-class
- leave-active-class
- leave-to-class
优先级高于普通类名,Vue 的过渡系统可以和 Animate.css等CSS 动画库结合使用
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="app">
<button @click="visible=!visible">Toggle</button>
<transition enter-active-class="animated fadeInDownBig" leave-active-class="animated fadeOutDownBig">
<p v-if="visible">test</p>
</transition>
</div>
</body>
</html>
JS
new Vue({
el: '#app',
data:{
visible:false
}
});
效果
JS 操作动画
可以在 attribute 中声明 JavaScript 钩子
- 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"
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
</head>
<body>
<div id="app">
<button @click="visible=!visible">Toggle</button>
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leaveEnter"
v-bind:css="false"
>
<p v-if="visible">test</p>
</transition>
</div>
</body>
</html>
JS
new Vue({
el: '#app',
data:{
visible:false
},
methods:{
beforeEnter:function(el){
el.style.opacity=0;
},
enter:function(el){
Velocity(el,{opacity:1},{duration:1000});
},
leaveEnter:function(el,done){
Velocity(el,{opacity:0},{complete:done});
}
}
});
效果
这些钩子函数可以结合 CSS transitions/animations 使用,也可以单独使用。
多元素过渡
同时生效的进入和离开的过渡不能满足所有要求,所以 Vue 提供了过渡模式
- in-out:新元素先进行过渡,完成之后当前元素过渡离开。
- out-in:当前元素先进行过渡,完成之后新元素过渡进入。
<transition name="fade" mode="out-in">...</transition>
多组件过渡
多个组件的过渡只需要使用动态组件
HTML
<transition name="component-fade" mode="out-in">
<component v-bind:is="view"></component>
</transition>
JS
new Vue({
el: '#transition-components-demo',
data: {
view: 'v-a'
},
components: {
'v-a': {
template: '<div>Component A</div>'
},
'v-b': {
template: '<div>Component B</div>'
}
}
})
列表过渡
<transition-group name="flip-list" tag="ul">
<li v-for="item in items" v-bind:key="item">
{{ item }}
</li>
</transition-group>
在渲染时,<transition-group> 默认时一个<span>,在上面的例子中 tag 的值 ul 会作为标签替换 <transition-group> 标签
其他
-
可复用过渡:将
<transition>或者<transition-group>作为根组件,然后将任何子组件放置在其中就可复用 -
动态过渡
在 Vue 中即使是过渡也是数据驱动的!动态过渡最基本的例子是通过 name attribute 来绑定动态值。
<transition v-bind:name="transitionName"> <!-- ... --> </transition>