1、动画基础:Vue过渡系统概述、CSS过渡与动画的区别、使用<transition>组件包裹元素、name属性与类名约定

1.1 Vue过渡系统:到底解决了什么问题?

说实话,我刚接触Vue动画时,第一反应是:「直接用CSS写动画不就行了?干嘛还要学一套新东西?」

后来在项目中踩了坑才明白——Vue过渡系统解决的核心问题,是元素进入/离开DOM时的状态管理

你想想看,一个普通的CSS动画,只能控制元素「已经在页面上」时的表现。但Vue的v-ifv-show切换时,元素是动态创建和销毁的。这时候,你需要在元素插入前插入瞬间离开前离开后这四个时间点,精准地控制样式。

手动去监听这些时机?太累了。Vue的<transition>组件就是来干这个的。

核心要点:Vue过渡系统本质上是「状态机 + CSS类名切换」的封装。它不创造新的动画能力,而是帮你管理动画的触发时机。

1.2 CSS过渡 vs CSS动画:别再傻傻分不清

很多初学者会把这两个概念混为一谈。我刚开始带团队时,就发现有人用animation去实现一个简单的淡入淡出,结果代码写得很复杂。

咱们来拆开看:

对比维度 CSS过渡(transition) CSS动画(animation)
触发方式 需要状态变化(如hover、类名切换) 可自动播放,无需外部触发
中间状态 只有开始和结束两个状态 可通过@keyframes定义多个关键帧
循环能力 不支持循环 支持无限循环
控制粒度 粗粒度,只能控制整体变化 细粒度,可控制每一帧
适用场景 简单的淡入淡出、位移、缩放 复杂的逐帧动画、循环动效

我的建议是:能用transition解决的,就别用animation。前者更轻量,性能也更好。只有当你需要「弹跳效果」、「逐帧播放」或「无限循环」时,才考虑animation

小技巧:Vue的<transition>组件默认使用CSS过渡。如果你想用CSS动画,需要在类名里写animation属性。两者可以混用,但我个人不建议——容易搞混触发时机。

1.3 使用<transition>组件:最简单的入门姿势

直接上代码。这是最基础的使用方式:

<template>
  <button @click="show = !show">切换</button>
  
  <transition name="fade">
    <p v-if="show">Hello, Vue 动画!</p>
  </transition>
</template>

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

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

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

这段代码做了什么事?说白了就是:当showtrue变成false时,Vue会自动给元素添加fade-leave-activefade-leave-to类名;反之则添加fade-enter-activefade-enter-from

嗯,这里要注意:<transition>只能包裹单个子元素。如果你有多个元素需要同时动画,得用<transition-group>,这个后面章节会讲。

我曾经踩过的坑<transition>不能直接包裹v-show控制的多个元素。如果你用v-show,动画只在第一次渲染时生效。后来我改用v-if + key属性才解决。

1.4 name属性与类名约定:Vue动画的命名规则

你注意到上面代码里的name="fade"了吗?这个name属性,就是Vue过渡系统的「命名空间」。

Vue内部有一套固定的类名约定:

  • 进入动画
    • {name}-enter-from:进入开始状态
    • {name}-enter-active:进入进行中状态
    • {name}-enter-to:进入结束状态
  • 离开动画
    • {name}-leave-from:离开开始状态
    • {name}-leave-active:离开进行中状态
    • {name}-leave-to:离开结束状态

如果你不设置name属性,默认值是v。也就是说,类名会变成v-enter-fromv-enter-active……

我个人习惯:每个<transition>都显式设置name。哪怕只有一个动画,也写上名字。为什么?因为项目大了以后,你根本记不住哪个v-对应哪个组件。命名清晰,维护起来才不痛苦。

记住这个规律

enter-from + enter-active → 元素出现

leave-from + leave-active → 元素消失

enter-toleave-to 是结束状态,通常和from相反。

1.5 实战中的避坑指南

最后分享几个我实际项目中遇到的坑:

  1. 动画不生效? 先检查name属性是否和CSS类名匹配。我犯过最蠢的错误是CSS里写fade-,但模板里写name="fade"——看起来没错对吧?结果发现CSS里少写了一个字母。
  2. 动画闪烁? 通常是enter-from和元素初始样式冲突。解决办法:在enter-from里显式覆盖初始样式。
  3. 动画卡顿? 别用display: none做动画。Vue的v-if本身就是操作display,你再叠加一个display动画,浏览器会懵。

我的调试习惯:在浏览器开发者工具里,勾选「:hov」状态,手动添加.fade-enter-active类名,看看动画是否正常。如果手动添加能生效,那就是Vue的时机问题;如果不生效,那就是CSS写错了。

好了,这一章的内容就到这里。记住:Vue过渡系统不复杂,核心就是6个类名 + 1个name属性。把基础打牢,后面学<transition-group>和JS钩子函数时,你会觉得特别顺畅。