第一章:Vue动画初探

为什么需要动画?

说实话,我刚开始做前端那会儿,也觉得动画就是个花架子。不就是让元素动一动嘛,能有什么实际价值?直到有一次,我负责一个后台管理系统,用户反馈说「点完按钮不知道有没有生效」——嗯,这就是没有动画的代价。

动画在UI里扮演的角色,比你想象的重要得多:

  • 引导注意力:新内容出现时,动画能告诉用户「看这里」
  • 解释变化:元素从A变到B,动画展示了「怎么变的」
  • 提升感知性能:加载动画让用户觉得「没那么慢」
  • 增加愉悦感:说白了,好看的动画让人心情好

我个人习惯把动画分成两类:功能性动画和装饰性动画。功能性动画解决「用户知不知道发生了什么」的问题,装饰性动画解决「用户觉得好不好看」的问题。先搞定前者,再追求后者。

Vue过渡系统概述

Vue的过渡系统,说白了就是一套帮你搞定元素「进场」和「离场」的机制。你想想看,一个组件从无到有,或者从有到无,中间发生了什么?Vue帮你管理这个过程。

核心就三个东西:

  • <Transition>:单个元素的进入/离开动画
  • <TransitionGroup>:列表的增删移动动画
  • <KeepAlive>:组件缓存,配合过渡使用效果更佳

我在项目中遇到过最典型的场景:弹窗组件。没有过渡时,弹窗「啪」一下出现,用户会被吓一跳。加了淡入淡出后,体验立马不一样了。

Vue的过渡系统不依赖任何第三方库。你完全可以只用CSS就做出不错的动画效果。当然,想玩更复杂的,可以搭配GSAP或Anime.js。

CSS过渡与动画基础回顾

在深入Vue之前,咱们先快速过一遍CSS里的动画基础。这部分如果你已经熟悉,可以跳过。但我建议你还是看一眼,因为Vue的过渡类名和CSS的过渡属性是直接对应的。

CSS Transition

CSS过渡,就是从一个状态平滑变到另一个状态。比如鼠标悬停时改变颜色:

.box {
  background-color: blue;
  transition: background-color 0.3s ease;
}

.box:hover {
  background-color: red;
}

这里要注意几个属性:

属性 作用 常用值
transition-property 指定哪些属性要过渡 all, opacity, transform
transition-duration 过渡时长 0.3s, 500ms
transition-timing-function 缓动函数 ease, linear, cubic-bezier()
transition-delay 延迟开始 0.1s

我曾经踩过一个坑:给 all 属性加过渡,结果页面里所有变化都变慢了。后来我改成只给 opacitytransform 加过渡,性能立马好了很多。记住,不要滥用 all

CSS Animation

CSS动画比过渡更强大。它可以定义多个关键帧,实现更复杂的动效:

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.box {
  animation: fadeIn 0.5s ease forwards;
}

关键帧动画的几个核心属性:

  • animation-name:指定 @keyframes 的名字
  • animation-duration:动画时长
  • animation-timing-function:缓动函数
  • animation-iteration-count:播放次数,infinite 表示无限循环
  • animation-direction:播放方向,alternate 可以来回播放
  • animation-fill-mode:动画结束后的状态,forwards 保持最后一帧

我个人习惯用 animation-fill-mode: forwards,这样动画结束后元素会保持在最终状态,不会「跳回」初始位置。这个小细节,能避免很多奇怪的闪烁问题。

Vue过渡类名机制

Vue的过渡系统,本质上就是在元素插入或移除时,自动给元素添加/移除特定的CSS类名。你只需要写好这些类名对应的样式,剩下的交给Vue。

以进入动画为例,Vue会依次添加三个类名:

  1. v-enter-from:进入的起始状态(比如 opacity: 0)
  2. v-enter-active:进入的过渡状态(比如 transition: opacity 0.3s)
  3. v-enter-to:进入的结束状态(比如 opacity: 1)

离开动画同理,对应 v-leave-fromv-leave-activev-leave-to

你想想看,Vue帮你做了最麻烦的部分——在正确的时机添加和移除类名。你只需要关心「开始长什么样」和「结束长什么样」,中间的过渡效果交给CSS。

一个最简单的例子

来看一个完整的例子,感受一下Vue过渡到底有多简单:

<template>
  <button @click="show = !show">切换</button>
  <Transition>
    <p v-if="show">Hello Vue Transition!</p>
  </Transition>
</template>

<script setup>
import { ref } from 'vue'
const show = ref(true)
</script>

<style>
.v-enter-active,
.v-leave-active {
  transition: opacity 0.5s ease;
}

.v-enter-from,
.v-leave-to {
  opacity: 0;
}
</style>

这段代码做了什么?

  • 点击按钮切换 show 的值
  • Vue检测到 v-if 变化,自动包裹 <Transition> 的逻辑
  • 元素出现时,添加 v-enter-fromv-enter-activev-enter-to
  • 元素消失时,添加 v-leave-fromv-leave-activev-leave-to
  • CSS过渡让透明度从0变到1,再从1变到0

就这么简单。你不需要写任何JavaScript来控制动画的启停,Vue全帮你搞定了。

如果你觉得 v- 前缀太通用,可以用 name 属性自定义前缀。比如 <Transition name="fade">,类名就变成 fade-enter-fromfade-enter-active 这样。我在项目中几乎每次都这么用,避免样式冲突。

小结

这一章我们聊了:

  • 动画为什么重要——不只是好看,更是为了好用
  • Vue过渡系统的三个核心组件
  • CSS过渡和动画的基础知识
  • Vue过渡类名的机制和用法

下一章,我们会深入 <Transition> 组件的各种用法,包括自定义类名、JavaScript钩子、以及和第三方动画库的集成。到时候我会分享一些我在实际项目中踩过的坑,保证有用。