文章目录
一、概述
Vue 在插入、更新或者移除 DOM 时,提供了多种不同方式的应用过渡效果。包括以下工具:
- 在 CSS 过渡和动画中自动应用 class
- 可以配合使用第三方 CSS 动画库,如 Animate.css
- 在过渡钩子函数中使用 JavaScript 直接操作 DOM
- 可以配合使用第三方 JavaScript 动画库,如 Velocity.js
在文章底部有本博客演示代码的下载链接,大家可以边测试使用边学习。
二、单元素 / 单组件的过渡
Vue 提供了 transition
的封装组件,在下列情形中,可以给任何元素和组件添加进入 / 离开过渡:
- 条件渲染 (使用
v-if
) - 条件展示 (使用
v-show
) - 动态组件
- 组件根节点
1、简单的使用案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>1</title>
<style>
.fade-enter {
opacity: 0;
}
.fade-enter-active {
/* 指定当 opacity 的属性改变时执行 transition 过渡效果 */
transition: opacity 1s;
color: red;
}
.fade-leave-to {
opacity: 0;
}
.fade-leave-active {
transition: opacity 1s;
color: green;
}
</style>
</head>
<body>
<div id="app">
<transition name="fade">
<h2 v-if="show">{
{message}}</h2>
</transition>
<button @click="btnClick">切换</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message:"hello",
show: true
},
methods: {
btnClick() {
this.show = !this.show;
}
}
});
</script>
</body>
</html>
解释: 当插入或删除包含在 transition 组件中的元素时,Vue 将会做以下处理:
- 自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加 / 删除 CSS 类名。
- 如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用(钩子函数将在下文进行介绍)。
- 如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡 / 动画,DOM 操作 (插入/删除) 在下一帧中立即执行。
2、transition讲解
transition
是 vue 内置的一个组件,我们可以直接使用。
<transition>
元素作为单个元素 / 组件的过渡效果。<transition>
只会把过渡效果应用到其包裹的内容上,而不会额外渲染 DOM 元素,也不会出现在可被检查的组件层级中。
注意:<transition>
只能用来包裹单个元素,如果包裹了多个元素,会报错:
<!-- 会报错 -->
<transition name="fade">
<h2 v-if="show">hello</h2>
<h2 v-if="show">webchang</h2>
</transition>
<!-- 这样就不会报错了 -->
<transition name="fade">
<h2 v-if="show">hello</h2>
<h2 v-else>webchang</h2>
</transition>
<!-- 或者这样 -->
<transition name="fade">
<div>
<h2 v-if="show">hello</h2>
<h2>world</h2>
</div>
</transition>
如果要包裹多个元素,需要使用 <transition-group>
(1)transition组件上定义的prop
name
:string类型,用于自动生成 CSS 过渡类名。例如:name: 'fade'
将自动拓展为.fade-enter
,.fade-enter-active
等。如果没有定义 name ,默认的类名前缀为"v"
,例如.v-enter
appear
:boolean类型,表示是否在初始渲染时使用过渡。默认为 false。type
:string类型,指定过渡事件类型,侦听过渡何时结束。有效值为"transition"
和"animation"
。默认 Vue.js 将自动检测出持续时间长的为过渡事件类型。mode
:string类型,控制离开/进入过渡的时间序列。有效的模式有"out-in"
和"in-out"
;默认同时进行。duration
:number类型或者对象类型:{ enter: number, leave: number } ,用来指定过渡的持续时间。默认情况下,Vue 会等待过渡所在根元素的第一个 transitionend 或 animationend 事件。
下边几个 prop 都是string类型,用来自定义过渡的类名:
- enter-class
- leave-class
- appear-class
- enter-to-class
- leave-to-class
- appear-to-class
- enter-active-class
- leave-active-class
- appear-active-class
(2)transition组件上的事件
- before-enter
- before-leave
- before-appear
- enter
- leave
- appear
- after-enter
- after-leave
- after-appear
- enter-cancelled
- leave-cancelled
- appear-cancelled
以上介绍的 prop 和 事件在下文进行讲解。
<!-- 简单使用 -->
<transition>
<div v-if="ok">toggled content</div>
</transition>
<!-- 使用动态组件实现组件过渡 -->
<transition name="fade" mode="out-in" appear>
<component :is="view"></component>
</transition>
<!-- 使用事件钩子 -->
<div id="transition-demo">
<transition @after-enter="transitionComplete">
<div v-show="ok">toggled content</div>
</transition>
</div>
3、过渡时的类名
在进入 / 离开的过渡中,会有 6 个 class 切换。
进入时:
v-enter
:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。v-enter-active
:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡 / 动画完成之后移除。 这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。v-enter-to
:vue 2.1.8 版及以上定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时v-enter
被移除),在过渡 / 动画完成之后移除。
离开时:
v-leave
:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。v-leave-active
:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡 / 动画完成之后移除。 这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。v-leave-to
:vue 2.1.8 版及以上定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时v-leave
被删除),在过渡 / 动画完成之后移除。
对于这些在过渡中切换的类名来说,如果使用了一个没有名字(没有 name 属性)的 <transition>
,则 v-
是这些类名的默认前缀。如果你使用了 <transition name="fade">
,那么 v-enter
会替换为 fade-enter
。
所以实现过渡的原理就是通过在某一时刻给 transition
包裹的的元素上动态添加和删除 class 类名的方式来实现。
4、自定义过渡的类名
我们可以通过在 transition
上添加以下 attribute
来自定义过渡类名:
enter-class
enter-active-class
enter-to-class
leave-class
leave-active-class
leave-to-class
他们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库,如 Animate.css 结合使用十分有用。如果某个过渡时期的类名没有自定义,那么用的还是原来的类名;如果被自定义了,添加动画和样式时要使用改动后的类名。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>2</title>
<style>
.fade-enter {
opacity