第5章Vue过渡和动画 在Vue 项目中使用过渡和动画能优化用户体验和页面的交互性、影响用户的行为、引 导用户的注意力以及帮助用户看到自己动作的反馈。例如,Vue 导航切换使用了过渡动 画,用户体验更友好。本章将结合案例讲解Vue 项目中过渡和动画的实现,及其在多个元 素或组件中的使用方法。 ● 了解过渡和动画的含义 ● 掌握内置过渡类名及自定义类名的使用方法 ● 掌握单元素、多元素、多组件的过渡 ● 掌握列表过渡的实现方法 你无法决定明天是晴是雨,也无法决定此刻的坚持能得到什么。但你能决定今天有 没有准备好雨伞,以及是否足够努力。胡思乱想少一点,脚踏实地多一些,就会距离成功 更近一步。 121 5.1 过渡与动画 5.1.1 了解过渡与动画 在CSS3中,过渡属性通过transition实现,动画属性通过animation实现。Vue也 实现了过渡与动画,在插入、更新或者移除DOM 时,Vue提供了多种过渡效果。Vue.js 会在适当的时机触发CSS过渡或动画,也可以提供相应的JavaScript钩子函数以在过渡 过程中执行自定义的DOM 操作。 Vue提供了内置的过渡封装组件,即transition组件,其语法格式如下: 1 <transition name="fade"> 2 <!--需要添加过渡的div 标签--> 3 <div></div> 4 </transition> 上述代码中,<transition>标签用来放置需要添加过渡的div元素,使用name属性 可以设置前缀,如果将name属性设置为fade,那么“fade-”就是在过渡中切换的类名前 缀,如fade-enter、fade-leave等。如果<transition>标签上没有设置name属性名,那么 “v-”就是这些类名的默认前缀,如v-enter、v-leave等。Vue提供了6个CSS类名,分别为 v-enter、v-enter-active、v-enter-to、v-leave、v-leave-active、v-leaveto。 通过<transition>标签搭配CSS动画(如@keyframes)可以实现动画效果,另外, <transition>标签还提供了一些钩子函数,可以结合JavaScript代码完成动画效果,具体 内容会在后文讲解。 5.1.2 transition 组件 Vue提供了transition的封装组件,在下列情形中,可以给任何元素和组件添加进入/ 离开过渡: ● 条件渲染(使用v-if) ● 条件展示(使用v-show) ● 动态组件 ● 组件根节点 Vue为transition提供了3个进入过渡的类和3个离开过渡的类,具体如表5-1所示。 表5-1 过渡类型 过渡状态过渡类型说 明 进入(enter) v-enter 进入过渡的开始状态,作用于开始的一帧 v-enter-active 进入过渡生效时的状态,作用于整个过程 v-enter-to 进入过渡的结束状态,作用于结束的一帧 122 续表 过渡状态过渡类型说 明 离开(leave) v-leave 离开过渡的开始状态,作用于开始的一帧 v-leave-active 离开过渡生效时的状态,作用于整个过程 v-leave-to 离开过渡的结束状态,作用于结束的一帧 表5-1中,6个类的生效时间如下。 ● v-enter:在元素被插入之前生效,在元素被插入之后的下一帧移除。 ● v-enter-active:在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡动 画完成之后移除。 ● v-enter-to:在元素被插入之后的下一帧生效(与此同时,v-enter被移除),在过渡 动画完成之后移除。 ● v-leave:在离开过渡被触发时立刻生效,下一帧被移除。 ● v-leave-active:在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在 过渡动画完成之后移除。 ● v-leave-to:在离开过渡被触发之后的下一帧生效(与此同时,v-leave被移除),在 过渡动画完成之后移除。 Vue过渡具体如图5-1所示。 图5-1 Vue过渡 下面通过一个案例演示如何使用内置的class类名实现过渡。 【例5-1】 使用内置的class类名实现过渡。 (1)创建文件夹chapter05,在该目录下创建demo01.html文件,具体代码如下: 1 <!DOCTYPE html> 2 <html lang="zh"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Transition 标签</title> 6 <style> 7 .box { 8 width: 200px; 123 9 height: 50px; 10 background-color: orange; 11 } 12 /* 进入和离开的过程*/ 13 .fade-enter-active, .fade-leave-active { 14 transition: width 3s; /* width 的变化,动画时间是3 秒*/ 15 } 16 /* 进入的初始状态和离开的结束状态*/ 17 .fade-enter, .fade-leave-to { 18 width: 0px; 19 } 20 /* 进入的结束状态和离开的初始状态*/ 21 .fade-enter-to, .fade-leave { 22 width: 200px; 23 } 24 </style> 25 </head> 26 <body> 27 <div id="app"> 28 <button type="button" @click="show=!show">Toggle</button> 29 <transition name="fade"> 30 <div class="box" v-if="show"> 31 <h1>Hello,Vue!</h1> 32 </div> 33 </transition> 34 </div> 35 <script src="vue.js"></script> 36 <script> 37 var vm = new Vue({ 38 el: '#app', 39 data: { 40 show: true 41 } 42 }) 43 </script> 44 </body> 45 </html> 在上述代码中,第29行将<transition>标签的name属性值设置为fade,这里的 fade是自定义类名前缀,因此在写CSS样式时,相对应的类名前缀以“fade-”开头;如果 transition不设置name属性,则第12~23行设置的CSS类均以“v-”为前缀;第30行的 div元素为一个长方形,通过使用v-if指令切换组件的可见性,通过show 设置显示的状 态,这样在单击按钮时,可以通过切换布尔值实现元素的显示和隐藏。在代码的第12~23 行编写以“fade-”开头的CSS样式,以实现动画效果。 124 (2)在浏览器中打开demo01.html文件,运行结果如图5-2所示。 图5-2 运行初始效果 在图5-2所示的页面中,单击Toggle按钮,会看到图形宽度变化的动画效果,其变化 过程中的某个效果如图5-3所示。 图5-3 动画效果 5.2 单元素/组件的过渡 实现过渡动画通常有三种方式,一是使用Vue的<transition>标签结合CSS样式实 现动画;二是利用animate.css结合transition实现动画;三是利用Vue中的钩子函数实现 动画。下面具体讲解实现过渡动画的三种方式。 5.2.1 使用@ keyframes 创建CSS 动画 使用@keyframes创建CSS动画时,v-enter类名在节点插入DOM 后不会立即删除, 而是在animationend(动画结束)事件触发时删除。 @keyframes规则创建动画是指将一套CSS样式逐步演变成另一套样式,在创建动 画的过程中可以多次改变CSS样式,通过百分比或关键词from 和to(等价于0和100%) 规定动画的状态。@keyframes的语法格式如下: 1 @keyframes animation-name { 2 keyframes-selector { css-styles; } 3 } 在上述语法中,keyframes-selector表示动画时长的百分比,css-styles表示一个或者 多个合法的CSS样式属性。 下面通过例5-2演示如何使用@keyframes创建CSS动画。 【例5-2】 使用@keyframes创建CSS动画。 125 (1)创建chapter05/demo02.html文件,具体代码如下: 1 <!DOCTYPE html> 2 <html lang="zh"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Transition 标签</title> 6 <style> 7 .box { 8 width: 200px; 9 height: 50px; 10 background-color: orange; 11 } 12 .v-enter-active { 13 animation: animate 1s; 14 } 15 .v-leave-active { 16 animation: animate 1s reverse; 17 } 18 @keyframes animate { 19 0%{ 20 opacity: 0; 21 transform: translateX(400px) scale(1); 22 } 23 50%{ 24 opacity: .5; 25 transform: translateX(200px) scale(1.5); 26 } 27 100%{ 28 opacity: 1; 29 transform: translateX(0) scale(1); 30 } 31 } 32 </style> 33 </head> 34 <body> 35 <div id="app"> 36 <button @click="show = !show">click</button> 37 <transition> 38 <div class="box" v-if="show">hello world</div> 39 </transition> 40 </div> 41 <script src="vue.js"></script> 42 <script> 126 43 var vm = new Vue({ 44 el: '#app', 45 data: { 46 show: true 47 } 48 }) 49 </script> 50 </body> 51 </html> 在上述代码中,第36行给button按钮添加了单击事件,通过单击按钮可以改变变量 show的值,<transition>标签没有设置name属性,所以第12~17行的CSS样式使用了 “v-”作前缀。第18~31行用于通过@keyframes规则创建名称为animate的动画样式, 其中,0表示动画的开始状态,100%表示动画的结束状态。 (2)在浏览器中打开demo02.html文件,如图5-4所示。 图5-4 页面初始效果 在图5-4所示的页面中,单击click按钮,会看到图形变化的动画效果,其变化过程中 的某个效果如图5-5所示。 图5-5 CSS动画 5.2.2 animate.css 结合transition 实现动画 animate.css是一个跨浏览器的CSS3动画库,它内置了很多经典的CSS3动画,使 用起来很方便。 animate.css的官网地址是https://daneden.github.io/animate.css/。 下面通过例5-3讲解如何使用自定义类名和animate.css库实现动画效果。 【例5-3】 使用自定义类名和animate.css库实现动画效果。 (1)创建chapter05/demo03.html文件,并且引入animate.css,具体代码如下: 1 <!DOCTYPE html> 2 <html lang="zh"> 3 <head> 127 4 <meta charset="UTF-8"> 5 <title>animation.css</title> 6 <link rel="stylesheet" href =" https://cdnjs. cloudflare. com/ajax/libs/animate. css/4. 1. 1/ animate.min.css"/> 7 <style> 8 .box { 9 width: 200px; 10 height: 50px; 11 background-color: orange; 12 } 13 </style> 14 </head> 15 <body> 16 <div id="app"> 17 <button @click="show = !show">click</button> 18 <transition 19 enter-active-class="animated bounceInLeft" 20 leave-active-class="animated bounceOutLeft" > 21 <div class="box" v-if="show">hello world</div> 22 </transition> 23 </div> 24 <script src="vue.js"></script> 25 <script> 26 var vm = new Vue({ 27 el: '#app', 28 data: { 29 show: true 30 } 31 }) 32 </script> 33 </body> 34 </html> 上述代码中,第6行引入了animate.css文件,第19、20行给<transition>标签设置 了enter-active-class与leave-active-class两个属性,用来自定义类名,属性值为animate.css动 画库中定义好的类名。例如,第19行的animatedbounceInLeft包含两个类名,animated 是基本的类名,任何想实现动画的元素都要添加它;bounceInLeft是动画的类名, bounceInLeft表示入场动画,bounceOutLeft表示出场动画。 (2)在浏览器中运行demo03.html文件,单击click按钮,即可看到文字显示或隐藏 的动画效果,如图5-6所示。 128 图5-6 初始效果 5.2.3 钩子函数实现动画 除了使用CSS动画外,还可以借助JavaScript完成动画。<transition>标签中定义 了一些动画钩子函数,可以用来实现动画,包括如下: 1 <transition> 2 @before-enter="beforeEnter" 3 @enter="enter" 4 @after-enter="afterEnter" 5 @enter-cancelled="enterCancelled" 6 @before-leave="beforeLeave" 7 @leave="leave" 8 @after-leave="afterLeave" 9 @leave-cancelled="leaveCancelled" 10 v-bind:css="false"> 11 </transition> 在上述代码中,入场钩子函数分别是beforeEnter(入场前)、enter(入场)、afterEnter (入场后)和enterCancelled(取消入场),出场钩子函数分别是beforeLeave(出场前)、leave (出场)、afterLeave(场后)和leaveCancelled(取消出场);第10行为仅使用JavaScript过 渡的元素添加v-bind:css="false",表示Vue会跳过CSS的检测,以免在过渡过程中受到 CSS的影响。 下面通过例5-4讲解如何使用钩子函数实现动画效果。 【例5-4】 使用钩子函数实现动画效果。 (1)创建chapter05/demo04.html文件,具体代码如下: 1 <!DOCTYPE html> 2 <html lang="zh"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>动画中的JavaScript 钩子函数的实现</title> 6 <script src="vue.js"></script> <style> .ball { 7 width: 15px; 8 height: 15px; 129 9 border-radius: 50%; 10 background-color: orangered; 11 } 12 </style> 13 </head> 14 <body> 15 <div id="app" > 16 <input type="button" value="快到碗里来" @click="flag=!flag"> 17 <transition 18 @before-enter="beforeEnter" 19 @enter="enter" 20 @after-enter="afterEnter"> 21 <div class="ball" v-show="flag"></div> 22 </transition> 23 </div> 24 <script> 25 new Vue({ 26 el: '#app', 27 data: { 28 flag: false 29 }, 30 methods: { 31 //设置小球开始动画之前的起始位置 32 beforeEnter(el) { 33 el.style.transform = "translate(0, 0)" 34 }, 35 enter(el, done) { 36 //这句话没有实际的作用,但如果不写,出不来动画效果 37 //可以认为el.offsetWidth 会强制动画刷新 38 el.offsetWidth 39 el.style.transform = "translate(150px, 450px)" 40 el.style.transition = 'all 1s ease' 41 //这里的done,其实就是afterEnter 这个函数,也就是说,done 是 //afterEnter 函数的引用 42 done() 43 }, 44 afterEnter(el){ 45 //动画完成之后 46 this.flag = !this.flag 47 } 48 } 49 }) 50 </script> 51 </body> 52 </html>