一、基本用法
<Transition>
是一个内置组件,这意味着它在任意别的组件中都可以被使用,无需注册。它可以将进入和离开动画应用到通过默认插槽传递给它的元素或组件上。进入或离开可以由以下的条件之一触发:
- 由
v-if
所触发的切换 - 由
v-show
所触发的切换 - 由特殊元素
<component>
切换的动态组件
1.1 最基本用法的示例
<template>
<button @click="show = !show">Toggle</button>
<Transition>
<p v-if="show">hello</p>
</Transition>
</template>
<style scoped>
.v-enter-active,
.v-leave-active {
transition: opacity 0.5s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
</style>
<Transition>
仅支持单个元素或组件作为其插槽内容。如果内容是一个组件,这个组件必须仅有一个根元素。
搭配原生 CSS 过渡 和 原生 CSS 动画 使用,可以实现更加细腻的动画展示效果。
可以通过
transitionend
或animationend
监听过渡和动画的事件。
1.2 一些附加描述
可以通过 type 属性显式告诉 Vue 需要关心哪种类型,传入的值是 animation
或 transition
。这在同时使用animation
或 transition
时是非常有用的
<Transition type="animation">...</Transition>
如果你想在某个节点初次渲染时应用一个过渡效果,你可以添加 appear
prop
<Transition appear>...</Transition>
可以通过 mode 属性指定过渡模式,属性值:in-out
和 out-in
<Transition mode="out-in">...</Transition>
使用深层级的 CSS 选择器,在 嵌套的深层级的元素上触发过渡效果
<template>
<Transition name="nested">
<div v-if="show" class="outer">
<div class="inner">
Hello
</div>
</div>
</Transition>
</tempalte>
<style scoped>
/* 应用于嵌套元素的规则 */
.nested-enter-active .inner,
.nested-leave-active .inner {
transition: all 0.3s ease-in-out;
}
.nested-enter-from .inner,
.nested-leave-to .inner {
transform: translateX(30px);
opacity: 0;
}
/* ... 省略了其他必要的 CSS */
</style>
可以通过 duration
属性来显式指定过渡的持续时间 (以毫秒为单位)
<Transition :duration="550">...</Transition>
二、CSS 过渡 class
一共有 6 个应用于进入与离开过渡效果的 CSS class。
v-enter-from
:进入动画的起始状态。在元素插入之前添加,在元素插入完成后的下一帧移除。v-enter-active
:进入动画的生效状态。应用于整个进入动画阶段。在元素被插入之前添加,在过渡或动画完成之后移除。这个 class 可以被用来定义进入动画的持续时间、延迟与速度曲线类型。v-enter-to
:进入动画的结束状态。在元素插入完成后的下一帧被添加 (也就是v-enter-from
被移除的同时),在过渡或动画完成之后移除。v-leave-from
:离开动画的起始状态。在离开过渡效果被触发时立即添加,在一帧后被移除。v-leave-active
:离开动画的生效状态。应用于整个离开动画阶段。在离开过渡效果被触发时立即添加,在过渡或动画完成之后移除。这个 class 可以被用来定义离开动画的持续时间、延迟与速度曲线类型。v-leave-to
:离开动画的结束状态。在一个离开动画被触发后的下一帧被添加 (也就是v-leave-from
被移除的同时),在过渡或动画完成之后移除。
<template>
<button @click='flag = !flag'>切换</button>
<transition>
<div v-if='flag' class="box"></div>
</transition>
</template>
<style scoped>
// 开始过渡
.v-enter-from{
background:red;
width:0px;
height:0px;
transform:rotate(360deg)
}
// 开始过渡了
.v-enter-active{
transition: all 2.5s linear;
}
// 过渡完成
.v-enter-to{
background:yellow;
width:200px;
height:200px;
}
// 离开的过渡
.v-leave-from{
width:200px;
height:200px;
transform:rotate(360deg)
}
// 离开中过渡
.v-leave-active{
transition: all 1s linear;
}
// 离开完成
.v-leave-to{
width:0px;
height:0px;
}
</style>
三、为过渡效果命名
我们可以给 <Transition>
组件传一个 name
prop 来声明一个过渡效果名。
<Transition name="fade">
...
</Transition>
对于一个有名字的过渡效果,对它起作用的过渡 class 会以其名字而不是 v
作为前缀。所以这个“fade”过渡的 class 应该是这样:
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
四、自定义过渡 class
你也可以向 <Transition>
传递以下的 props 来指定自定义的过渡 class:
enter-from-class
enter-active-class
enter-to-class
leave-from-class
leave-active-class
leave-to-class
你传入的这些 class 会覆盖相应阶段的默认 class 名。这个功能在你想要在 Vue 的动画机制下集成其他的第三方 CSS 动画库时非常有用,比如 Animate.css:
安装 animate.css
npm install animate.css
在 main.js 引入
import 'animate.css'
在 Transition 组件中使用
<Transition
name="custom-classes"
enter-active-class="animate__animated animate__tada"
leave-active-class="animate__animated animate__bounceOutRight"
>
<p v-if="show">hello</p>
</Transition>
五、Transition 生命周期钩子
JavaScript 中可以通过监听 <Transition>
组件事件的方式在过渡过程中挂上钩子函数
<script setup>
// 在元素被插入到 DOM 之前被调用
// 用这个来设置元素的 "enter-from" 状态
function onBeforeEnter(el) {}
// 在元素被插入到 DOM 之后的下一帧被调用
// 用这个来开始进入动画
function onEnter(el, done) {
// 调用回调函数 done 表示过渡结束
// 如果与 CSS 结合使用,则这个回调是可选参数
done()
}
// 当进入过渡完成时调用。
function onAfterEnter(el) {}
function onEnterCancelled(el) {}
// 在 leave 钩子之前调用
// 大多数时候,你应该只会用到 leave 钩子
function onBeforeLeave(el) {}
// 在离开过渡开始时调用
// 用这个来开始离开动画
function onLeave(el, done) {
// 调用回调函数 done 表示过渡结束
// 如果与 CSS 结合使用,则这个回调是可选参数
done()
}
// 在离开过渡完成、
// 且元素已从 DOM 中移除时调用
function onAfterLeave(el) {}
// 仅在 v-show 过渡中可用
function onLeaveCancelled(el) {}
</script>
<template>
<Transition
@before-enter="onBeforeEnter"
@enter="onEnter"
@after-enter="onAfterEnter"
@enter-cancelled="onEnterCancelled"
@before-leave="onBeforeLeave"
@leave="onLeave"
@after-leave="onAfterLeave"
@leave-cancelled="onLeaveCancelled"
>
<!-- ... -->
</Transition>
</template>
当只用 JavaScript 过渡的时候,在
enter
和leave
钩子中必须使用done
进行回调。(通过:css="false"
属性显式地向 Vue 表明可以跳过对 CSS 过渡的自动探测,除了性能稍好一些之外,还可以防止 CSS 规则意外地干扰过渡效果。)
六、配合 slot 实现可复用过渡效果
得益于 Vue 的组件系统,过渡效果是可以被封装复用的。要创建一个可被复用的过渡,我们需要为 <Transition>
组件创建一个包装组件,并向内传入插槽内容:
<!-- MyTransition.vue -->
<script>
// JavaScript 钩子逻辑...
</script>
<template>
<!-- 包装内置的 Transition 组件 -->
<Transition
name="my-transition"
@enter="onEnter"
@leave="onLeave">
<slot></slot> <!-- 向内传递插槽内容 -->
</Transition>
</template>
<style>
/*
必要的 CSS...
注意:避免在这里使用 <style scoped>
因为那不会应用到插槽内容上
*/
</style>
现在 MyTransition
可以在导入后像内置组件那样使用了:
<MyTransition>
<div v-if="show">Hello</div>
</MyTransition>