概述

Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。包括以下工具:

  • 在 CSS 过渡和动画中自动应用 class
  • 可以配合使用第三方 CSS 动画库,如 Animate.css
  • 在过渡钩子函数中使用 JavaScript 直接操作 DOM
  • 可以配合使用第三方 JavaScript 动画库,如 Velocity.js

上一篇章讲解了使用第三方CSS动画库Animate.css来设置动画效果,本章节来看看如何使用钩子函数来实现。

那么前面的方法都可以实现动画效果了,为什么还要特定用多一个JavaScript的钩子方法来设置呢?主要是因为无法单独设置一个入场和出场中某个步骤的动画效果。

例如:单独只设置入场或者单独只设置出场的动画效果。对于这种动画效果,应用的场景例如「加入购物车」这样的情况,按照之前的使用CSS的方法是无法设置出来的。

下面来看看官网中的使用介绍。

JavaScript 钩子函数

可以在属性中声明 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 })
}
}
})

下面使用钩子函数来实现一个运动半场的动画效果。

使用JavaScript钩子函数实现一个小球半场动画

1.首先写一个点击按钮【购物】,然后一个红色小球,用于展示购物的效果
<!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>

浏览器查看如下:

30. Vue使用JavaScript 钩子函数实现半场动画_JavaScriptimage-20200202111435190
2.使用v-on设置进入变量的钩子函数
30. Vue使用JavaScript 钩子函数实现半场动画_JavaScript_02image-20200202111811425
3.在对应的钩子函数打印对应信息,查看相关钩子的执行情况
30. Vue使用JavaScript 钩子函数实现半场动画_JavaScript_03image-20200202112646624

在浏览器中查看,点击按钮,当切换v-if显示小球的时候,对应的钩子函数会如何执行,执行哪些钩子函数。如下:

30. Vue使用JavaScript 钩子函数实现半场动画_JavaScript_04image-20200202113150291
4.在对应的钩子函数中,编写小球的动画js代码
30. Vue使用JavaScript 钩子函数实现半场动画_JavaScript_05image-20200202114818725

在enter钩子函数中的el.offsetWidth很重要,如果不写则不会出来动画效果,当然写其他offsetHeight也是可以的。

效果如下:

30. Vue使用JavaScript 钩子函数实现半场动画_JavaScript_06image-20200202115009434

30. Vue使用JavaScript 钩子函数实现半场动画_JavaScript_07

到这里已经实现了小球通过购物车点击,触发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>