transition组件同时实现过渡和动画

在了解了 transition 组件实现 CSS 过渡效果和 CSS 动画效果之后,那么能否同时实现过渡和动画呢?这种应用场景确实存在,下面就来讲解一下如何给一个元素同时添加 “渐隐渐现” 和 “变大缩小” 的效果。

先来介绍一个知识点,在之前的代码中,通过给 transition 组件设置 name 属性来标识使用哪个动画或者过渡效果,除此之外,还可以通过以下特性来给 <transition> 设置属性来自定义过渡类名,这些属性分别是:

  • enter-from-class

  • enter-active-class

  • enter-to-class

  • leave-from-class

  • leave-active-class

  • leave-to-class

由于同时配置过渡效果和动画效果采用之前的默认方式 v-xxx 定义动画会有冲突,因此需要自定义类名,上面的 6 个类名分别对应 transition 组件实现过渡或者动画的 6 个时刻。接下来通过自定义类名来分别指定过渡和动画,如示例代码 5-4-1 所示。

<style>
@keyframes bounce-in {
    0% {
        transform: scale(0);
    }
    50% {
        transform: scale(1.5);
    }
    100% {
        transform: scale(1);
    }
}
.bounce-enter-active {
    animation: bounce-in 1s ;
}
.bounce-leave-active {
    animation: bounce-in 1s reverse;
}
.fade-enter-from,.fade-leave-to {
    opacity: 0
}
.fade-enter-active,.fade-leave-active {
    transition: opacity 1s
}
</style>
<div id="app">
    <button @click="clickCallback">切换</button>
    <transition enter-from-class="fade-enter-from"
                enter-to-class="fade-enter-to"
                leave-to-class="fade-leave-to"
                enter-active-class="bounce-enter-active fade-enter-active"
                leave-active-class="bounce-leave-active fade-leave-active">
        <div v-if="show" style="text-align: center;">Hello!</div>
    </transition>
</div>

在这段代码中,使用了 animationCSS 样式和 transitionCSS 样式,然后在自定义类名时设置了多个 class,尤其是 enter-active-classleave-active-class。这样就实现了同时套用两种过渡动画效果。

在代码中,也强制给过渡和动画设置了同样的时间,都为 1 秒(1s)。但是,在一些应用场景中,需要给同一个元素同时设置过渡和动画效果,比如 animation 很快被触发并完成了,而 transition 效果还没结束。对于这种情况,就需要使用 type 属性并设置 animationtransition 来明确声明需要 Vue 监听的类型。代码如下:

<transition type="animation"></transition>

这样,<transition> 就会以动画结束的时间为主。

在大多数情况下,<transition> 可以根据配置的 CSS 属性自动计算出过渡/动画效果的完成时机。这个时机是根据其在过渡/动画效果的根元素的第一个 transitionendanimationend 事件触发的时间点计算出来的。然而也可以不遵循这样的设定,例如,有一个精心编排的一系列过渡/动画效果,其中一些嵌套的内部元素相比于整体过渡/动画效果的根元素有延迟的或更长的过渡/动画效果。在这种情况下,就可以用 <transition> 组件上的 duration 属性定制一个显性的过渡/动画持续时间(以毫秒计),代码如下:

<transition :duration="1000">...</transition>

也可以更加细化地定制进入和移出的持续时间:

<transition :duration="{ enter: 500, leave: 800 }">...</transition>