Vue过渡 & 动画
本章节我们主要介绍 Vue.js 的过渡与动画。如何编写 CSS 动画、如何配合第三方 CSS 动画库、过渡的使用、如何使用第三方 JavaScript 动画库。本小节的相对之前有些难度,同学们在阅读一遍之后如果不能完全掌握,建议反复阅读,并把本小节的所有案例自己实现一遍,相信通过多次的练习一定可以掌握。
Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡。
以下工具:
1、在 CSS 过渡和动画中应用 class;
2、配合使用第三方 CSS 动画库,如 Animate.css;
3、在过渡中使用 JavaScript 直接操作 DOM;
4、配合使用第三方 JavaScript 动画库,如 Vety.js。
使用 transition 组件包裹需要使用过渡的 DOM 元素。例如:
<transition name = "transition-name">
<div>...</div>
</transition>
接下来让我们先看淡入淡出的实现:
<!DOCTYPE html>
<html lang="en">
<head>
< charset="UTF-8">
< name="viewport" content="width=device-width, initial-scale=1.0">
< http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity s
}
.fade-enter, .fade-leave-to {
opacity:
}
</style>
</head>
<body>
<div id = "app">
<button v-on:click = "show = !show">{{ show ? '隐藏' : ''}}</button>
<transition name="fade">
<p v-show = "show" >hello !</p>
</transition>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type = "text/javascript">
var vm = new Vue({
el: '#app',
data: {
show:true
},
methods : {
}
});
</script>
</html>
解释:
那么,transition 组件是如何做到这样的过渡的呢?
我想,同学们肯定猜想到当元素切换状态的时候,我们定义的样式会作用于元素 <p>
。那么,到底是不是这样呢?
打开控制台,检索到 <p>
上,我们可以清晰地看到:
实际上 Vue 在与隐藏的过渡中,提供了 6 个 class 来切换:
对于这些在过渡中切换的类名来说,如果你使用没有名字的 <transition>
,则 v- 是这些类名的认前缀。如果你使用了 <transition name="test-transition">
,那么 v 会替换为 test-transition。例如:test-transition-enter、test-transition-enter-active、test-transition-leave…
在日常开发中,我们经常会使用 CSS 过渡来实现一些简单的动画。接下来我们用示例来学习如何使用:
<!DOCTYPE html>
<html lang="en">
<head>
< charset="UTF-8">
< name="viewport" content="width=device-width, initial-scale=1.0">
< http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.fade-enter-active {
transition: all s ease;
}
.fade-leave-active {
transition: all s cubic-bezier(, , , );
}
.fade-enter, .fade-leave-to {
transform: translateY(px);
opacity: ;
}
</style>
</head>
<body>
<div id = "app">
<button v-on:click = "show = !show">{{ show ? '' : '隐藏'}}</button>
<transition name = "fade">
<p v-show = "show" >Hello !</p>
</transition>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type = "text/javascript">
var vm = new Vue({
el: '#app',
data: {
show:true
}
});
</script>
</html>
解释:
同样,我们可以使用 CSS 动画来实现元素的过渡。CSS 动画类似 CSS 过渡,在过渡的不同阶段对应的 Class 会作用于元素。但是在动画中 v-enter 类名在节点插入 DOM 后不会立即,而是在 animationend 事件触发时。
相信同学们在日常业务开发中一定使用过 Dialog,接下来我们就使用 CSS 动画来实现它的过渡:
<!DOCTYPE html>
<html lang="en">
<head>
< charset="UTF-8">
< name="viewport" content="width=device-width, initial-scale=1.0">
< http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#app{
text-align: center;
}
.dialog{
width: px;
height: px;
border: px solid #333;
margin: px auto;
text-align: center;
line-height: px;
}
.bounce-enter-active {
animation: bounce-in ms;
}
.bounce-leave-active {
animation: bounce-out ms;
}
@keyframes bounce-in {
0% {
transform: scale();
}
50% {
transform: scale();
}
100% {
transform: scale();
}
}
@keyframes bounce-out {
0% {
transform: scale();
}
100% {
transform: scale();
}
}
</style>
</head>
<body>
<div id = "app">
<button v-on:click = "show = !show">{{ show ? ' Dialog' : '隐藏 Dialog'}}</button>
<transition name = "bounce">
<p v-show = "show" class="dialog">Dialog...</p>
</transition>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type = "text/javascript">
var vm = new Vue({
el: '#app',
data: {
show:false
}
});
</script>
</html>
解释:
在之前的两个案例中,我们通过给 transition 设置 name 来指定元素在不同阶段的样式类名,但有时候希望使用的过渡类名,我们可以通过给 transition 设置以下来达到需求:
过渡的类名优先级高于普通的类名,这样就能很好地与第三方(如:animate.css)的动画库结合使用。
在很多情况下,Vue 可以得出过渡的完成时机。认情况下,Vue 会等待其在过渡的根元素的第 或 animationend 事件。然而也可以不这样设定 —— 比如,我们可以拥有精心编排的一系列过渡,其中一些嵌套的内部元素相比于过渡的根元素有延迟的或更长的过渡。
种情况下你可以用 组件上的 duration 定制显性的过渡持续时间 (以毫秒计):
<transition :duration="1000">...</transition>
你也可以定制进入和移出的持续时间:
<transition :duration="{ enter: 400, leave: 600 }">...</transition>
transition 组件在过渡的不同阶段会触发相应的:
<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"
>
<p>...</p>
</transition>
这些可以结合 CSS transitions/animations 使用,也可以单独使用。
当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则,它们将被同步,过渡会立即完成。
推荐对于仅使用 JavaScript 过渡的元素 v-bind:css="false"
,Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。
接下来我们来看使用和 实现过渡动画的例子:
<!DOCTYPE html>
<html lang="en">
<head>
< charset="UTF-8">
< name="viewport" content="width=device-width, initial-scale=1.0">
< http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.hello{
width: px;
height: px;
border: px solid red;
margin: auto;
}
</style>
</head>
<body>
<div id = "app">
<button @click="show = !show">
切换状态
</button>
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leave"
v-bind:css="false"
>
<p v-if="show">
Demo
</p>
</transition>
</div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vety/1.2.3/vety.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type = "text/javascript">
var vm = new Vue({
el: '#app',
data: {
show:false
},
methods: {
beforeEnter: function (el) {
el.style.opacity =
el.style.transformOrigin = 'left'
},
enter: function (el, done) {
Vety(el, { opacity: , fontSize: '1.4em' }, { duration: })
Vety(el, { fontSize: '1em' }, { complete: done})
},
leave: function (el, done) {
Vety(el, { translateX: '20px', rotateZ: '45deg' }, { duration: })
Vety(el, { rotateZ: '90deg' }, { loop: })
Vety(el, {
rotateZ: '45deg',
translateY: '30px',
translateX: '30px',
opacity:
}, { complete: done })
}
}
});
</script>
</html>
解释:
有时候我们希望给元素设置初始渲染的过渡,可以通过给 transition 设置 appear 的 attribute
:
<transition appear>
<!-- ... -->
</transition>
这里认和进入 / 离开过渡一样,同样也可以 CSS 类名:
<transition
appear
appear-class="v-appear-class"
appear-to-class="v-appear-to-class"
appear-active-class="v-appear-active-class"
>
<!-- ... -->
</transition>
同样地,可以使用 JavaScript 钩子:
<transition
appear
v-on:before-appear="beforeAppear"
v-on:appear="appear"
v-on:after-appear="afterAppear"
v-on:appear-cancelled="appearCancelled"
>
<!-- ... -->
</transition>
接下来我们看完整的示例:
<!DOCTYPE html>
<html lang="en">
<head>
< charset="UTF-8">
< name="viewport" content="width=device-width, initial-scale=1.0">
< http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.hello{
width: px;
height: px;
border: px solid red;
margin: auto;
}
.v-appear-class{
opacity: ;
}
.v-appear-to-class{
opacity: ;
}
.v-appear-active-class{
transition: all s;
}
</style>
</head>
<body>
<div id = "app">
<button v-on:click = "show = !show">隐藏</button>
<transition
appear
appear-class="v-appear-class"
appear-to-class="v-appear-to-class"
appear-active-class="v-appear-active-class"
v-on:before-appear="beforeAppear"
v-on:appear="appear"
v-on:after-appear="afterAppear"
v-on:appear-cancelled="appearCancelled"
>
<p v-show = "show" class="hello">Hello !</p>
</transition>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type = "text/javascript">
var vm = new Vue({
el: '#app',
data: {
show:true
},
methods: {
beforeAppear() {
console.log('beforeAppear')
},
appear() {
console.log('appear')
},
afterAppear() {
console.log('afterAppear')
},
appearCancelled() {
console.log('appearCancelled')
},
}
});
</script>
</html>
解释:
本小节我们介绍了如何使用 transition 实现过渡和动画,主要以下知识点: