Vue 过渡

与其它框架不同,Vue.js 为开发人员提供了对 Vue.js 应用程序动画的内置支持,包括过渡和动画。转换以一种简单直接的方式实现,开发人员可以轻松配置并将其添加到他们的应用程序中。Vue.js 转换机制支持 CSS 转换、使用 JavaScript 进行编程操作,甚至与第三方动画库(例如 GSAP 或 Animate.css)集成。

首先,我们将讨论过渡和动画之间的区别。当组件(或元素)从一种状态移动到另一种状态时,例如将鼠标悬停在按钮上、从一个页面导航到另一页面、显示弹出模式等,就会发生转换。同时,动画就像过渡,但不仅限于两种状态。了解过渡的基础知识可以让您开始使用动画。

过渡元素

在此示例中,为了启用单个组件或元素的转换,Vue.js 提供了内置转换组件,该组件将环绕目标元素,如 ./src/components/HelloWorld.vue 中所示:

<transition name="fade-in">
    <h1>{{ msg }}</h1>
</transition>

过渡(transition)组件为任何目标元素或组件添加两种过渡状态(进入(enter)和离开(leave)),包括具有条件渲染 (v-if) 和条件显示 (v-show) 的组件。

该组件接收一个名为 name 的 prop,它表示过渡的名称(在本例中为淡入),也是过渡类名称的前缀,接下来将对此进行讨论。

过渡 Class

Vue.js 为离开(leave)/进入(enter)实现了基于 CSS 和基于 class 的过渡效果,因此过渡将通过一组 class 选择器应用于目标组件。

每个类选择器都有 v- 前缀,以防过渡(transition)组件上没有给出 name 属性。

对于这些在过渡中切换的类名来说,如果你使用一个没有名字的 <transition>,则 v- 是这些类名的默认前缀。如果你使用了 <transition name="my-transition">,那么 v-enter 会替换为 my-transition-enter

该标准类(class)分为两个主要组:

第一组转换类用于组件首次显示时的进入(enter)转换。以下是 enter 转换类的列表:

  • v-enter(或 <name>-enter):这是起始状态,在添加或更新组件之前添加到组件。一旦转换结束,此类将被删除。 在 src/components/HelloWorld.vue 的 <style> 部分,我们将 .fade-in-enter 起始状态设置为完全隐藏,opacity: 0

    <style>
    .fade-in-enter {
        opacity: 0;
    }
    </style>
  • v-enter-active(或 <name>-enter-active):此类定义组件主动进入过渡时的延迟、持续时间和缓动曲线。它将在插入组件之前添加到组件中,在整个进入阶段应用于组件,并在效果完成后删除。

    让我们添加 .fade-in-enter-active,它将在 3 秒内转换到不透明状态:

    .fade-in-enter-active {
        transition: opacity 3s easein;
    }
  • v-enter-to(或 <name>-enter-to):这是 enter 的最后一个子状态,在插入组件后添加效果框架,并在效果完成时移除效果框架。在我们的示例中,我们不需要定义任何内容,因为此状态的不透明度(opacity)值应该为 1。

第二组类由离开(leave)转换组成,当组件被禁用或从视图中删除时触发:

  • v-leave(或 <name>-leave):这是离开(leaving)转换的起始状态。与 v-enter-to 类似,我们不需要为该状态定义样式效果。

  • v-leave-active(或 <name>-leave-active):这在离开(leaving)阶段应用,其作用与 v-enter-active 类似。由于我们想要淡出效果,因此我们将使用与 fade-in-enter-active 相同的样式:

    .fade-in-enter-active, .fade-in-leave-active {
        transition: opacity 3s ease-in;
    }
  • v-leave-to(或 <name>-leave-to):这是结束状态,其行为与 v-enter-to 类似。由于该组件将从视图中消失,因此我们将重用为 enter fade-in-enter 的开始阶段定义的样式:

    .fade-in-enter, .fade-in-leave-to {
        opacity: 0;
    }

以下屏幕截图是迄今为止描述的所有转换(transition)状态的回顾:

image 2023 10 15 11 09 11 896
Figure 1. Figure 7.1: Diagram of transition phases
总结

在进入/离开的过渡中,会有 6 个 class 切换。

  • v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。

  • v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。

  • v-enter-to:2.1.8 版及以上定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。

  • v-leave:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。

  • v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。

  • v-leave-to:2.1.8 版及以上定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

在本节中,我们研究了三种不同的进入转换状态和三种不同的离开转换状态。我们还介绍了如何使用过渡状态在用户按下按钮时缓慢淡出某些文本。

组件的动画

由于动画基本上是过渡的扩展形式(具有两个以上的状态),CSS 动画用法同 CSS 过渡,区别是在动画中 v-enter 类名在节点插入 DOM 后不会立即删除,而是在 animationend 事件触发时删除。

animationend 是一个 DOM 事件,一旦 CSS 动画完成执行就会触发,条件是目标元素仍然存在于 DOM 中并且动画仍然附加到该元素。

对于下一个示例,在 <template> 部分中,我们可以使用动画 CSS 效果作为显示 msg 的 h1 元素的包装来定义一个名为 Slide 的新过渡。此过渡提供了进入时从左侧滑动到中心、离开时从左侧滑动到中心的动画效果。

首先,使用 CLI 和以下命令生成 vue 入门项目:

vue create hello-world

接下来,打开项目并进入 src/components/HelloWorld.vue,然后修改现有的 <h1>{{msg}}</h1> 代码:

<transition name="slide">
    <h1 v-if="show">{{ msg }}</h1>
</transition>

<style> 中,我们需要定义幻灯片动画效果的关键帧:

@keyframes slide {
    0% { transform: translateX(-100px)}
    100% { transform: translateX(0px)}
}

相关的转换类将被分配以下样式:

.slide-enter, .slide-leave-to {
    transform: translateX(-100px);
}
.slide-enter-active {
    animation: slide 5s;
}
.slide-leave-active {
    animation: slide 5s reverse;
}

这意味着在进入的开始阶段和离开的结束阶段,文本位置将距离页面上指定位置 -100px。浏览器将使用幻灯片关键帧为元素设置动画,持续时间为 5 秒,在离开的活动状态下,动画将与进入的活动阶段完全相反。

您还需要添加一个显示数据变量。 您可以通过修改现有导出来完成此操作,如下所示:

<script>
export default {
    name: 'HelloWorld',
    data: {
        showHello: true,
    },
    props: {
        msg: String
    }
}
</script>

这样,我们就实现了我们的动画。现在出现了下一个挑战:如果我们想要组合不同的动画或过渡效果来离开和进入状态,或者为这些状态使用外部 CSS 库,该怎么办?让我们看一下自定义转换类。

自定义过渡 Class

在本节中,我们将再次从使用 vue create hello-world 创建的默认入门项目开始。 可以选择通过以下属性提供自定义类并替换传统的默认值,而不是设置转换名称并让 Vue.js 机制填充所需的类名称。

要进入状态,请使用以下命令:

  • enter-class

  • enter-active-class

  • enter-to-leave

要离开状态,请使用以下命令:

  • leave-class

  • leave-active-class

  • leave-to-class

我们将首先根据前面的示例创建一个文件,但现在我们将在进入状态的活动阶段使用摇摆(swing)动画效果,并在离开状态的活动阶段使用 tada 效果。我们将在转换(transition)组件中定义 enter-active-class 和 leave-active-class 属性,如下所示:

<transition
    name="slide"
    enter-active-class="swing"
    leave-active-class="tada"
>
    <h1 v-if="show">{{ msg }}</h1>
</transition>

<style> 部分,我们只需要定义 .tada.swing,不需要任何后缀模式:

.tada {
    animation-fill-mode: both;
    animation-name: tada;
    animation-duration: 3s;
}

.swing {
    animation-fill-mode: both;
    transform-origin: top center;
    animation-duration: 2s;
    animation-name: swing;
}

然后添加专用关键帧来设置动画:

@keyframes tada {
    0% {
        transform: scale3d(1, 1, 1);
    }
    10%, 20% {
        transform: scale3d(.8, .9, .8) rotate3d(0, 0, 1, -5deg);
    }
    30%, 50%, 70%, 90% {
        transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 5deg);
    }
    40%, 60%, 80% {
        transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -5deg);
    }
    100% {
        transform: scale3d(1, 1, 1);
    }
    @keyframes swing {
        20% { transform: rotate(5deg); }
        40% { transform: rotate(-10deg); }
        60% { transform: rotate(5deg); }
        80% { transform: rotate(-10deg); }
        100% { transform: rotate(0deg); }
    }
}

您还需要添加一个显示数据变量。 您可以通过修改现有导出(export)来完成此操作,如下所示:

<script>
export default {
    name: 'HelloWorld',
    data: {
        showHello: true,
    },
    props: {
        msg: String
    }
}
</script>

当我们使用 yarn serve 命令运行应用程序时,我们将分别设置进入和离开的动画。以下屏幕截图显示了屏幕现在的显示方式:

image 2023 10 15 11 21 29 697
Figure 2. Figure 7.2: Swing animation effect on action

您应该会看到欢迎文本在旋转时缩小,从图 7.2 中所示的内容转变为以下内容:

image 2023 10 15 11 22 13 721
Figure 3. Figure 7.3: tada animation effect on action

在本节中,我们研究了创建自定义过渡效果。作为例子,我们制作了 swing 和 tada。 我们通过在样式表中定义过渡类,然后为每个效果添加关键帧来做到这一点。该技术可用于创建各种自定义过渡效果。在下一节中,我们将了解 JavaScript 挂钩以及如何将它们用于更复杂的动画。