前言:
Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。包括以下工具:
- 在 CSS 过渡和动画中自动应用 class
- 可以配合使用第三方 CSS 动画库,如 Animate.css
- 在过渡钩子函数中使用 JavaScript 直接操作 DOM
- 可以配合使用第三方 JavaScript 动画库,如 Velocity.js
那么接下来就让我们好好Vue中的过度与动画.
1. 过渡或动画的了解
Vue 提供了 transition
的封装组件,来处理过渡以及动画
1.1 使用过渡或动画的场景
在下列情形中,可以给任何元素和组件添加进入/离开过渡
- 条件渲染(使用
v-if
) - 条件展示(使用
v-show
) - 动态组件
- 组件的根节点
1.2 使用说明
只有dom从隐藏到显示,或从显示到隐藏, 才能使用vue的过渡或动画
动画的元素需要被Vue所提供的组件
transition
所包裹在插入或删除
transition
包裹元素时,Vue会在恰当的实际添加或删除类名如果过渡的组件提供了
JavaScript钩子函数
,则Vue会在恰当的时机调用这些钩子函数
如果没有找到
JavaScrip钩子函数
,并且也没有检测到CSS过渡/动画,则会在下一帧中立即执行
2. Vue 过渡的使用
2.1 认识过渡
Vue过渡/动画两个过程,分别为进入和离开.
Vue会在不同的需要过渡的元素在进入/离开的不同时机给元素添加不同的类名
不同阶段的类名:
Enter | Enter | Leave | Leave |
---|---|---|---|
Opacity:0 | Opacity:1 | Opacity:1 | Opacity:0 |
v-enter | v-enter-to | v-leave | v-leave-to |
v-enter-active | v-enter-active | v-leave-active | v-leave-active |
2.2 过度类名的了解
在进入/离开的过渡中,会有 6 个 class 切换。
-
v-enter
:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。 -
v-enter-active
:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。 -
v-enter-to
:2.1.8 版及以上定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时v-enter
被移除),在过渡/动画完成之后移除。 -
v-leave
:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。 -
v-leave-active
:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。 -
v-leave-to
:2.1.8 版及以上定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时v-leave
被删除),在过渡/动画完成之后移除。
现在我们对于这些类名有了一定的了解之后,我们通过案例来加深对于这些类名的理解和记忆
2.3 示例:
需要动画的元素
2.4 过渡前缀
过渡前缀说明
- 如果你使用一个没有名字的
,则v-
是这些类名的默认前缀。 - 如果使用了
,那么v-enter
会替换为myname-enter
。
示例:
需要动画的元素
2.5 在过渡中使用贝塞尔曲线
需要动画的元素
3. CSS动画
我们处理可以在Vue中使用过渡transition
,还可以使用CSS动画animation
需要动画的元素
3. 自定义过度动画的类名
我们可以通过以下 attribute
来自定义过渡类名:
enter-class
enter-active-class
-
enter-to-class
(2.1.8+) leave-class
leave-active-class
-
leave-to-class
(2.1.8+)
他们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库,如 Animate.css 结合使用十分有用。
示例:
需要动画的元素
4.动画插件库
animated.css 使用的是keyframes 的动画
4.1 安装
安装
npm install animate.css --save-dev
引入
4.2 使用cdn
4.3 使用
Hello world
使用animation动画库的好处就是不需要我们自己去写负责的动画
4.4 最开始入场动画
Hello world
但是你会发现最开始是没有入场动画的,如果我也希望网页一打开最开始就有入场动画
应该如下处理,添加appear属性
Hello wold
4.5 animation动画和transition过渡一起使用
4.5.1 动画过渡一起使用
示例:
Hello wold
此时你会发现animated.css的animation动画的时长和transition的时长不一样,那么要以哪个为准呢,其实vue也不知道,所以我们可以添加一个type属性来制定动画时长以谁为准
Hello wold
4.5.2 自定义过渡/动画时间
同时我们也可以自定义动画时长,通过绑定duration,5秒后
Hello wold
我们也可以单独定义入场动画时长和出场动画时长
Hello wold
5. Vue中的JS动画
vue中的js动画是通过vue提供给的动画钩子函数来绑定事件,然后在事件函数中处理对应的动画
5.1 动画入场的钩子函数
before-enter 动画入场运动前一刻执行
enter 动画运动时执行
after-enter 在动画enter函数中运行完毕并调用回调done时执行
Hello wold
5.2 动画出场的钩子函数
同样动画出场的钩子函数与动画入场的钩子函数使用是一致的
before-leave
leave
after-leave
我们发现js动画没有动画时长需要我么自己调整,我们可以借助Velocity.js处理js动画
注意:
- 使用JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则过渡会立即完成。
- 对于仅使用 JavaScript 过渡的元素添加
v-bind:css="false"
,Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。
例如:
Hello wold
5.3 Vue中JS动画与Velocity.js的结合
首先进入官网下载Velocity.js
然后引入
再次使用
Hello wold
6.Vue中多个元素之间的动画
6.1 多个元素之前切换动画
多元素过渡,就是利用v-if
或者v-show
等指令,切换元素的显示, 需要显示的元素就会有入场动画,需要隐藏的就有出场动画.
过渡示例:
Hello wold
Bye wold
一定要注意动画内部两个div的标签复用,如果不加key,只会看到内容改变了,透明度样式并没有发生变化,这就是vue中的dom复用的机制,就是为了提升效率, 所以我们要加可以表示 唯一的dom
注意:
- 当有相同标签名的元素切换时,需要通过
key
属性设置唯一的值来标记以让 Vue 区分它们
-
key
属性的作用,在讲v-for
已经介绍过来, 为了不让DOM元素复用
- DOM元素复用是Vue提升性能的手段,但是因为DOM元素复用了,也就没有动画效果了,
- 因此通过
key
属性阻止DOM元素复用
6.2 出场入场动画先后顺如
默认出场入场动画是同时进行的,同时生效的进入和离开的过渡不能满足所有要求,所以Vue提供了过渡模式
mode属性说明
Vue在transition标签上提供了一个mode属性,来设置出场入场动画的先后顺序
mode的属性值为in-out
,则为先执行入场动画,等入场动画执行完毕后在执行出场动画,
mode属性值为out-in
则先执行出场动画,在执行入场动画
示例:
Hello wold
Bye wold
7. Vue中组件之间的动画
7.1. 不利用动态组件的写法
示例:
7.2. 利用动态组件的方式切换组件
8. Vue中的列表过度
目前为止,关于过渡我们已经讲到:
- 单个节点
- 同一时间渲染多个节点中的一个
那么怎么同时渲染整个列表,比如使用 v-for
?在这种场景中,使用
组件。
特点:
-
标签会以一个真实元素呈现:默认是
。也可以通过 tag
属性 更换为其他元素。
-
过渡模式
不可用,因为我们不再相互切换特有的元素。
- 内部元素总是需要提供唯一的
key
属性 值。
- CSS 过渡的类将会应用在内部的元素中,而不是这个组/容器本身。
示例如下:
vue中的列表过渡使用的是transition-group标签嵌套
{{item.title}}
其实transition-group的原理就是给每一个列表循环的单独的元素套了一层transition标签,说白了,还是单个元素的过渡动画
就像这样
Hello World
Hello World
Hello World
....
注意,for循环的key值尽量不要用index索引,会导致性能降低,其次项目功能上也会造成一定的影响,如果能不用index作为key值,尽量不要用index作为key值
9. 封装Vue动画
利用组件和slot的方式,将动画封装成一个组件,这样可以通过组件调用发方式复用相同动画
Hello wold
当然你还可以继续进一步封装完善, 达到你想要的目的