Vue一个案例引发「动画」的使用总结
项目开发中动画有着很重要的作用,而且也是用到的地方非常多,例如:鼠标的进入离开,弹窗效果,组件的显示隐藏,列表的切换等等,可以说我们网页上的动画无处不在,也有人说了,这些东西也可以不使用动画。
对,你说的没错可以不使用,但是,首先你要说服你的产品经理咱能不能简单点,不搞这么多虚的来点实际的,说完之后我估计你们俩得立马干起来,其次,在你的网页上不使用动画不够逼格啊,而且咱们的网页也不够生动,没有活力,由此可见动画的不可或缺性。
上面只是开个玩笑,下面咱们进入主题,看看 Vue 中如何更好更简单的添加动画。
首先,Vue 在插入,修改或者移除 DOM 时,提供了多种不同的添加动画的方法,在 Vue 中我们使用
<transition>
和
<transition-group>
组件时,Vue 会给我们提供一些内置的 CSS 类与 JS 钩子函数。
先来看看我们要实现一个什么样子的案例效果
图中的例子是一个非常常见的图片切换效果,不过在这个例子中我们只是单纯的实现图片的切换,看起来非常的生硬,没有任何的过渡效果,下面我们来给图片加一点动画的效果,让它看起来非常的有逼格。
CSS 过渡
被
<transition>
包裹的组件,在组件的不同阶段会产生不同的 class 类名进行切换
- v-enter/v-leave:动画的第一帧
- v-enter-acive/v-leave-active:动画运行的阶段,一些过渡属性会放置在这里,如:时间,延迟等
- v-enter-to/v-leave-to:动画结束,最后一帧
官网上的一张图片非常友好的展示了这个切换的过程。
v-
是 Vue 中默认的类名前缀,我们在使用的过程中如果一直使用默认的命名方式的话,必然会导致一些冲突,所以 Vue 给我们提供了一个自定义命名的方案,我们只需要给
<transition>
添加一个 name 属性即可。
既然我们知道了方法,我们就来给它加一个简单的动画。
<template>
<ul class="tabs-list">
v-for="tab in tabs"
:key="tab.id"
:class="{active: tabOn === tab.id}"
@mouseover="tabOn = tab.id"
:href="tab.url" target="_blank"
{{tab.name}}
<transition name="flip">
<img v-show="tabOn === tab.id" :src="tab.imgUrl">
</transition>
<template>
<style lang="scss" scoped>
.flip-enter-active {
transition: transform 1s;
.flip-leave-active {
transition: transform 1s;
.flip-enter,
.flip-leave-to {
transform: scaleY(0);
</style>
CSS 动画
与上面 CSS 过渡不同的是,我们这里说的 CSS 动画是利用 @keyframes 来创建与上面类似的动画效果。
<style lang="scss" scoped>
@keyframes scaleY-in {
transform: scaleY(0);
50% {
transform: scaleY(0.5);
100% {
transform: scaleY(1);
.flip-enter-active {
animation: scaleY-in 1s;
.flip-leave-active {
animation: scaleY-in 1s reverse;
</style>
使用第三方动画库
Vue 中给我们提供了自定义 CSS 类名的方法,非常好的支持了与第三方动画库的结合。
- enter-class / leave-class
- enter-active-class / leave-active-class
- enter-to-class / leave-to-class
上面两个动画都是我们自己动手写出来的,但是有些时候我们自己手写的并不是那么完美,或者项目的时间比较紧张,这个时候选择第三方库就是一个比较好的方案。我们继续利用 Animate.css 动画库修改我们上面的例子。
<transition
name="flip"
enter-active-class="animated rotateIn"
leave-active-class="animated rotateOut"
<img v-show="tabOn === tab.id" :src="tab.imgUrl">
</transition>
JavaScript 动画
Vue 中还给我们提供了一些钩子函数,我们可以使用 JavaScript 钩子函数构建动画。
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@enter-cancelled="enterCancelled"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
@leave-cancelled="leaveCancelled"
:css="false"
</transition>
所有钩子都会传入一个 el(元素)参数,enter/leave 函数还会传入一个 done 函数作为参数。它会告知我们的动画完成,我们绑定了 css 为 false,告诉组件跳过 CSS 的检测,使用 JavaScript。
我们结合 Velocity.js 动画,来修改完成我们的动画效果。
<transition
@enter="enter"
@leave="leave"
:css="false"
<img v-show="tabOn === tab.id" :src="tab.imgUrl">
</transition>
<script>
methods: {
enter(el, done) {
Velocity(el, { scaleY: "0" });
Velocity(el, { scaleY: "0.5" }, { duration: 1000 });
Velocity(el, { scaleY: "1" }, { complete: done });
leave: function(el, done) {
Velocity(el, { scaleY: "1" });
Velocity(el, { scaleY: "0.5" }, { duration: 1000 });
Velocity(el, { scaleY: "0" }, { complete: done });
</script>
过渡模式
我们再来回头看看上面的例子,不管我们使用何种方式实现的动画,你会发现一个问题就是,动画在切换的时候两者(进入/离开)是同时进行的,有些时候,我们并不希望产生这种效果,对我们的动画效果非常的不友好,比如我们看看下面的这个例子。
<template>
<div class="translate-container" @click="clickHandler">
<transition name="slide">
<img v-if="isShow" src="./feature/03.jpg" key="first">
<img v-else src="./feature/04.jpg" key="second">
</transition>
</template>
<script>
export default {
methods: {
clickHandler() {
this.isShow = !this.isShow;
</script>
<style lang="scss" scoped>
.slide-enter-active,
.slide-leave-active {
transition: all 0.5s;
.slide-leave-to,
.slide-enter {
transform: scaleY(0);