Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。包括以下工具:
上一篇章讲解了使用第三方CSS动画库Animate.css来设置动画效果,本章节来看看如何使用钩子函数来实现。
那么前面的方法都可以实现动画效果了,为什么还要特定用多一个JavaScript的钩子方法来设置呢?主要是因为无法单独设置一个入场和出场中某个步骤的动画效果。
例如:单独只设置入场或者单独只设置出场的动画效果。对于这种动画效果,应用的场景例如「加入购物车」这样的情况,按照之前的使用CSS的方法是无法设置出来的。
下面来看看官网中的使用介绍。
可以在属性中声明 JavaScript 钩子
<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>
可以看到这里使用v-on绑定了动画过程的多个钩子函数,具体的动画效果只要在对应的钩子函数进行编写即可。
// ... methods: { // -------- // 进入中 // -------- beforeEnter: function (el) { // ... }, // 当与 CSS 结合使用时 // 回调函数 done 是可选的 enter: function (el, done) { // ... done() }, afterEnter: function (el) { // ... }, enterCancelled: function (el) { // ... }, // -------- // 离开时 // -------- beforeLeave: function (el) { // ... }, // 当与 CSS 结合使用时 // 回调函数 done 是可选的 leave: function (el, done) { // ... done() }, afterLeave: function (el) { // ... }, // leaveCancelled 只用于 v-show 中 leaveCancelled: function (el) { // ... } }
这些钩子函数可以结合 CSS transitions/animations 使用,也可以单独使用。
❝当只用 JavaScript 过渡的时候,「在 enter 和 leave 中必须使用 done 进行回调」。否则,它们将被同步调用,过渡会立即完成。
推荐对于仅使用 JavaScript 过渡的元素添加 v-bind:css="false",Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。
❞
一个使用 Velocity.js 的简单例子:
<!-- Velocity 和 jQuery.animate 的工作方式类似,也是用来实现 JavaScript 动画的一个很棒的选择 --> <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script> <div id="example-4"> <button @click="show = !show"> Toggle </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>
new Vue({ el: '#example-4', data: { show: false }, methods: { beforeEnter: function (el) { el.style.opacity = 0 el.style.transformOrigin = 'left' }, enter: function (el, done) { Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 }) Velocity(el, { fontSize: '1em' }, { complete: done }) }, leave: function (el, done) { Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 }) Velocity(el, { rotateZ: '100deg' }, { loop: 2 }) Velocity(el, { rotateZ: '45deg', translateY: '30px', translateX: '30px', opacity: 0 }, { complete: done }) } } })
下面使用钩子函数来实现一个运动半场的动画效果。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 1.导入vue.js库 --> <script src="lib/vue.js"></script> <!-- 编写小球的显示样式 --> <style> #boll{ margin-top: 10px; width: 15px; height: 15px; border-radius: 50%; background: lightpink; } </style> </head> <body> <div id="app"> <!-- 使用v-on绑定click事件执行切换show变量,用于控制下面p标签的v-if --> <button @click="show = !show"> 加入购物车 </button> <!-- 设置动画小球 --> <transition> <div v-if="show" id="boll"></div> </transition> </div> <script> // 2\. 创建一个Vue的实例 var vm = new Vue({ el: '#app', data: { show: true }, }) </script> </body> </html>
浏览器查看如下:
image-20200202111435190在浏览器中查看,点击按钮,当切换v-if显示小球的时候,对应的钩子函数会如何执行,执行哪些钩子函数。如下:
image-20200202113150291在enter钩子函数中的el.offsetWidth很重要,如果不写则不会出来动画效果,当然写其他offsetHeight也是可以的。
效果如下:
image-20200202115009434到这里已经实现了小球通过购物车点击,触发v-if显示入场动画效果。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 1.导入vue.js库 --> <script src="lib/vue.js"></script> <!-- 编写小球的显示样式 --> <style> #boll{ margin-top: 10px; width: 15px; height: 15px; border-radius: 50%; background: lightpink; } </style> </head> <body> <div id="app"> <!-- 使用v-on绑定click事件执行切换show变量,用于控制下面p标签的v-if --> <button @click="show = !show"> 加入购物车 </button> <!-- 设置动画小球 --> <transition v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:after-enter="afterEnter" v-on:enter-cancelled="enterCancelled" > <div v-if="show" id="boll"></div> </transition> </div> <script> // 2\. 创建一个Vue的实例 var vm = new Vue({ el: '#app', data: { show: true }, methods:{ // -------- // 进入中 // -------- beforeEnter: function (el) { // 开始准备进入动画状态 console.log("执行进入动画中的beforeEnter钩子函数"); // 设置小球开始动画之前的,起始位置 el.style.transform = "translate(0, 0)"; }, // 当与 CSS 结合使用时 // 回调函数 done 是可选的 enter: function (el, done) { // 已经进入动画状态,用于设置动画效果 console.log("执行进入动画中的enter钩子函数"); // 这句话,没有实际的作用,但是,如果不写,出不来动画效果; // 可以认为 el.offsetWidth 会强制动画刷新 el.offsetWidth; // enter 表示动画 开始之后的样式,这里,可以设置小球完成动画之后的,结束状态 el.style.transform = "translate(150px, 450px)"; el.style.transition = 'all 1s ease'; // 执行完毕,使用done方法回调afterEnter done() }, afterEnter: function (el) { // 进入动画状态之后,执行结束恢复的操作 console.log("执行进入动画中的afterEnter钩子函数"); // 执行动画完毕后,再次隐藏小球 this.show = !this.show }, enterCancelled: function (el) { // 当取消进入动画状态的时候执行 console.log("执行进入动画中的enterCancelled钩子函数"); }, } }) </script> </body> </html>