Vue 在插入、更新或移除 DOM 时,提供多种不同方式的应用过渡效果,包括以下工具:
- 在 CSS 过渡和动画中自动应用 class
- 可以配合使用第三方 CSS 动画库,如 Animate.css
- 在过渡钩子函数中使用 javascript 直接操作 DOM
- 可以配合使用第三方 javascript 动画库,如 Velocity.js
单元素/组件的过渡
Vue 提供了 transition
的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡
- 条件渲染(使用
v-if
) - 条件展示(使用
v-show
) - 动态组件
- 组件根节点
代码示例
<template>
<div>
<button @click="show = !show">Toggle</button>
<transition name="fade">
<p v-if="show">Hello Vue!</p>
</transition>
</div>
</template>
<script>
export default {
name: 'oneTransition',
data() {
return {
show: true
}
}
}
</script>
<style scoped>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
结果:
当插入或删除包含在 transition
组件中的元素时,vue将会做如下处理:
- 自动嗅探目标元素是否应用了 css 过渡或动画,如果是,在恰当的时机添加/删除 css 类名。
- 如果过渡组件提供了 javascript 钩子函数,这些钩子函数将在恰当的时机被调用
- 如果没有找到 JavaScript 钩子并且也没有检测到 css 过渡/动画,DOM 操作(插入/删除)在下一帧中立即执行(指浏览器逐帧动画机制,和 vue 的 nextTick 概念不同)
过渡的类名
在进入/离开的过渡中,会有 6 个 class 切换
v-enter
: 定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。v-enter-active
:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间、延迟和曲线函数。v-enter-to
: 定义进入过渡的结束状态。在元素被插入之后下一帧生效(与此同时v-enter
被移除),在过渡/动画完成之后移除。v-leave-active
: 定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除,这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。v-leave-to
: 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效(与此同时v-leave
被删除,在过渡/动画完成之后移除)。
对于这些在过渡中切换的类名来说,如果你使用一个没有名字的<transition>
,则v-
是这些类名的默认前缀。如果你使用了<transition name="my"
,那么v-enter
会替换为my-enter
。
v-enter-active
和v-leave-active
可以控制进入/离开过渡的不同的缓和曲线。
css过渡
常用的过渡都是使用css过渡
<template>
<div>
<div class="content">
<transition name="one">
<div class="box1" v-show="oneBox"></div>
</transition>
<transition name="two">
<div class="box2" v-show="twoBox"></div>
</transition>
</div>
</div>
</template>
<script>
export default {
name: 'cssTransition',
data() {
return {
oneBox: false,
twoBox: false,
}
},
mounted() {
this.$nextTick(() => {
this.oneBox = true
this.twoBox = true
})
}
}
</script>
<style scoped>
.content {
width: 700px;
margin: 0 auto;
height: auto;
display: flex;
align-items: center;
justify-content: space-between;
}
.box1 {
width: 300px;
height: 300px;
background-color: rgb(238, 241, 13);
}
.box2 {
width: 300px;
height: 300px;
background-color: rgb(13, 138, 241);
}
.one-enter, .one-leave-to {
opacity: 0;
transform: translateX(-100px);
}
/* 可以设置不同的进入和离开动画 */
/* 设置持续时间和动画函数 */
.one-enter-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.one-leave-active {
transition: all 0.5s;
}
.two-enter, .two-leave-to {
opacity: 0;
transform: translateX(100px);
}
.two-enter-active, .two-leave-active {
transition: all 0.5s;
}
</style>
css动画
css动画用法同css过渡,区别是在动画中v-enter
类名在节点插入DOM后不会立即删除,而是在 animationend
事件触发时删除。
自定义过渡的类名
我们可以通过以下 attribute 来自定义过渡类名
enter-class
enter-active-class
enter-to-class
leave-class
leave-active-class
leave-to-class
他们的优先级高于普通的类名,这对于Vue的过渡系统和其他第三方css动画库,如 Animate.css 结合使用十分有用
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
<div id="example-3">
<button @click="show = !show">
Toggle render
</button>
<transition
name="custom-classes-transition"
enter-active-class="animated tada"
leave-active-class="animated bounceOutRight"
>
<p v-if="show">hello</p>
</transition>
</div>
new Vue({
el: '#example-3',
data: {
show: true
}
})
显性的过渡持续时间
在很多情况下,vue可以自动得出过渡效果的完成时机。默认情况下,vue会等待其在过渡效果的根元素的第一个 transitionend
或 animationend
事件。然而也可以不这样设定–比如,我们可以拥有一个精心编排的一系列过渡效果,其中一些嵌套的内部元素相比于过渡效果的根元素有延迟的或更长的过渡效果。
在这种情况下你可以用 <transition>
组件上的 duration
prop 定制一个显性的过渡持续时间(以毫秒计)
<transition :duration="1000">...</transition>
你也可以定制进入和移除的持续时间
<transition :duration="{ enter: 500, leave: 800 }">...</transition>