Transition
<Transition>
会在一个元素或组件进入和离开 DOM
时应用动画。本章节会介绍如何使用它。
内置组件可以在任意的组件中被使用,无需注册。它可以将进入和和离开动画应用到传递给它的元素或组件上
进入或离开的触发条件
- 由 v-if 所触发的切换
- 由 v-show 所触发的切换
- 由特殊元素
切换的动态组件 - 改变特殊的 key 属性
1 | <button @click="show = !show">Toggle</button> |
1 | .v-enter-active, |
<Transition>
仅支持单个元素或组件作为其内容。如果内容是一个组件,这个组件必须仅有一个根元素。
当一个 <Transition>
组件中的元素被插入或移除时,会发生下面这些事情:
Vue
会自动检测目标元素是否应用了CSS
过渡或动画,如果是,则一些CSS过渡class
会在适当的时机被添加和移除- 如果有作为监听器的
Javascript钩子
,这些钩子函数会在适当时机被调用 - 如果没有探测到
CSS过渡或动画
,也没有提供JavaScript
钩子,那么DOM
的插入,删除操作将在浏览器的下一个动画帧后执行
基于CSS的过渡效果
一共有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
被移除的同时),在过渡或动画完成之后移除。
为过渡效果命名
1 | <Transition name="fade"> |
那前面那几个对应的class
会以其姓名而不是v
作为前缀
1 | .fade-enter-active, |
CSS的transition
<Transition>
一般都会搭配原生 CSS
过渡一起使用,这个 transition CSS
属性是一个简写形式,使我们可以一次定义一个过渡的各个方面,包括需要执行动画的属性、持续时间和速度曲线。
1 | <Transition name="slide-fade"> |
1 | /* |
CSS的animation
原生 CSS
动画和 CSS transition
的应用方式基本上是相同的,只有一点不同,那就是 *-enter-from
不是在元素插入后立即移除,而是在一个 animationend
事件触发时被移除。
对于大多数的 CSS
动画,我们可以简单地在 *-enter-active
和 *-leave-active class
下声明它们
1 | <Transition name="bounce"> |
1 | .bounce-enter-active { |
关键帧 @keyframes
规则通过在动画序列中定义关键帧(或 waypoints
)的样式来控制 CSS
动画序列中的中间步骤。
即先0 -> 放大1.25 -> 原来大小
自定义过渡 class
也可以向 <Transition>
传递以下的 props
来指定自定义的过渡 class
传入的class
会覆盖相应阶段的默认class
名。这个功能在想要集成其它的第三方CSS
动画库时非常有用
1 | <!-- 假设你已经在页面中引入了 Animate.css --> |
同时使用transition和animation
Vue
需要附加事件监听器,以便知道过渡何时结束。可以是 transitionend
或 animationend
,这取决于你所应用的 CSS
规则。如果你仅仅使用二者的其中之一,Vue
可以自动探测到正确的类型。
然而在某些场景中,你或许想要在同一个元素上同时使用它们两个。举例来说,Vue
触发了一个 CSS
动画,同时鼠标悬停触发另一个 CSS
过渡。此时你需要显式地传入 type prop
来声明,告诉 Vue
需要关心哪种类型,传入的值是 animation
或 transition
:
1 | <Transition type="animation">...</Transition> |
深层级过渡与显式过渡时长
尽管过渡 class
仅能应用在 <Transition>
的直接子元素上,我们还是可以使用深层级的 CSS
选择器,在深层级的元素上触发过渡效果:
1 | <Transition name="nested"> |
1 | /* 应用于嵌套元素的规则 */ |
然而,这会带来一个小问题。默认情况下,<Transition>
组件会通过监听过渡根元素上的第一个 transitionend
或者 animationend
事件来尝试自动判断过渡何时结束。而在嵌套的过渡中,期望的行为应该是等待所有内部元素的过渡完成。
在这种情况下,你可以通过向 <Transition>
组件传入 duration prop
来显式指定过渡的持续时间 (以毫秒为单位)。总持续时间应该匹配延迟加上内部元素的过渡持续时间:
1 | <Transition :duration="{ enter: 500, leave: 800 }">...</Transition> |
JavaScript 钩子
1 | <Transition |
1 | export default { |
在使用仅由 JavaScript
执行的动画时,最好是添加一个 :css="false" prop
。这显式地向 Vue
表明可以跳过对 CSS
过渡的自动探测。除了性能稍好一些之外,还可以防止 CSS
规则意外地干扰过渡效果:
1 | <Transition |
可复用过渡效果
创建一个MyTransition.vue
组件
1 | <!-- MyTransition.vue --> |
scoped
属性是HTML5
中的新属性,是一个布尔属性。如果使用该属性,则样式仅仅应用到style
元素的父元素及其子元素
现在 MyTransition
可以在导入后像内置组件那样使用了:
1 | <MyTransition> |
出现时过渡
在某个节点初次渲染时应用一个过渡效果
1 | <Transition appear> |
元素间过渡
除了通过 v-if
/ v-show
切换一个元素,我们也可以通过 v-if
/ v-else
/ v-else-if
在几个组件间进行切换,只要确保任一时刻只会有一个元素被渲染即可:
1 | <Transition> |
过渡模式
在之前的例子中,进入和离开的元素都是在同时开始动画的,因此我们不得不将它们设为 position: absolute
以避免二者同时存在时出现的布局问题。
然而,很多情况下这可能并不符合需求。我们可能想要先执行离开动画,然后在其完成之后再执行元素的进入动画。手动编排这样的动画是非常复杂的,好在我们可以通过向 <Transition>
传入一个 mode prop
来实现这个行为:
1 | <Transition mode="out-in"> |
组件间过渡
<Transition>
也可以作用于动态组件之间的切换:
1 | <Transition name="fade" mode="out-in"> |
1 | <script> |
动态过渡
<Transition>
的 props
(比如 name
) 也可以是动态的!这让我们可以根据状态变化动态地应用不同类型的过渡:
1 | <Transition :name="transitionName"> |
这个特性的用处是可以提前定义好多组 CSS
过渡或动画的 class
,然后在它们之间动态切换。
使用 Key Attribute 过渡
有时为了触发过渡,需要强制重新渲染 DOM
元素。
比如计数器组件
1 | <script> |
有了 key
属性,Vue
就知道在 count
改变时创建一个新的 span
元素,因此 Transition
组件有两个不同的元素在它们之间进行过渡
小结:
- 各种过渡都是说明可以有各种各样的目标对象。根据时间点,元素,组件,key值,name进行过渡操作