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-on
设置进入变量的钩子函数image-20200202111811425
image-20200202112646624
在浏览器中查看,点击按钮,当切换v-if
显示小球的时候,对应的钩子函数会如何执行,执行哪些钩子函数。如下:
image-20200202113150291
image-20200202114818725
在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>