Transition组件是Vue控制DOM状态变化节奏的核心机制,通过三阶段类名(如v-enter-from/active/to)和JS钩子精准调度动画,需正确配置可动画属性、transition声明及mode等细节。

Transition 组件不是“加个动画就完事”的装饰品,而是 Vue 控制 DOM 状态变化节奏的核心机制。 它不直接执行动画,而是通过精准注入和移除 CSS 类、触发 JS 钩子,把动画控制权交还给开发者——这意味着效果是否自然、时机是否准确,全取决于你对类名生命周期和触发条件的理解。
过渡类名的三阶段逻辑必须吃透
Vue 在元素进入或离开时,并非只加一个 class,而是按严格顺序切换三组类,每组承担不同职责:
- v-enter-from → v-enter-active → v-enter-to:进入全过程。v-enter-from 是“还没出现”的初始态(如 opacity: 0),v-enter-to 是“完全呈现”的终态(如 opacity: 1),而 v-enter-active 是唯一带 transition 或 animation 声明的地方,它决定用什么属性动、动多久、怎么缓动。
- v-leave-from → v-leave-active → v-leave-to:离开全过程。v-leave-from 是“还在原位”的起点(如 transform: scale(1)),v-leave-to 是“彻底消失/移出”的终点(如 transform: scale(0) 或 left: 100vw),v-leave-active 同样必须声明动画规则,否则 leave 阶段不会动。
- 注意:v-enter 和 v-leave 在 2.1.8+ 已被废弃,应统一使用 -from / -to 后缀版本;若用了 name="fade",所有类前缀自动变为 fade-enter-from,而非 v-fade-enter-from。
常见失效原因与对应解法
写好样式却没动画?大概率卡在这几个细节上:
- 过渡目标元素没有“可动画属性”:比如对 display: none 元素设 opacity 过渡无效,因为 display 变化是立即发生的。应改用 v-show 或配合 visibility + opacity。
- v-enter-active 或 v-leave-active 缺少 transition / animation 声明:这两个类只是“开关”,不写 transition: all 0.3s 就等于没通电。
- 元素被 v-if 切换但父容器高度塌陷:过渡期间内容消失导致父级高度归零,造成“闪退”。可在父容器加 min-height 或使用 v-show 配合 height 过渡。
- 多个同级 transition 冲突:比如两个 v-if 互斥元素共用一个 transition,Vue 默认同时过渡。此时需加 mode="out-in",确保旧元素走完再进新元素。
用 JS 钩子补足 CSS 力所不及的场景
CSS 擅长属性渐变,但遇到需要 DOM 测量、第三方库动画、或异步加载后才启动的动效,JS 钩子就是关键出口:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
立即学习“前端免费学习笔记(深入)”;
- 常用钩子:@before-enter、@enter、@after-enter、@before-leave、@leave、@after-leave。其中 @enter 和 @leave 接收 el 和 done 两个参数,调用 done() 表示 JS 动画结束,否则 Vue 会等待超时(默认 5s)才强制清理。
- 典型用法:在 @enter 中用 GSAP 动画 el,最后调用 done();或在 @before-enter 中获取元素原始位置,@enter 中用 requestAnimationFrame 实现精准位移插值。
- 注意:若同时写了 CSS transition 和 JS enter 钩子,Vue 会优先等待 JS 的 done() 调用,CSS 过渡会被忽略——这是可控的设计,不是 bug。
配合路由做页面级转场更实用
单页应用中,页面切换是最典型的过渡场景。只需把
- 基础写法:<Transition name="slide"><RouterView /></Transition>,所有路由组件共享 slide 过渡。
- 差异化处理:利用路由元信息 meta,动态绑定 name:<Transition :name="$route.meta.transition || 'fade'">,再在各路由配置里写 meta: { transition: 'slide-left' }。
- 强制刷新过渡:当复用同一组件(如 /user/1 → /user/2)时,Vue 默认跳过卸载/挂载,导致过渡不触发。加 key="$route.fullPath" 即可让 Vue 视为新实例,重新走完整 enter/leave 流程。
不复杂但容易忽略:过渡效果的本质是状态变化的“时间显影”,Transition 组件提供的是一套精确到帧的调度协议,而不是魔法盒子。写对类名、配好触发条件、该交还给 JS 时别硬扛——流畅的动效就自然浮现了。

















