Transition 组件原理
<Transition> 看起来像是“给元素加动画”,但它本质上做的是:
在元素进入和离开时,帮你管理一套可控的过渡生命周期。
所以它既不是纯 CSS,也不是单纯的 JavaScript 动画 API,而是 Vue 在“节点插入/移除”时加上的一层协调机制。
面试速答(30 秒版 TL;DR)
Transition只包裹一个根节点或组件。- 它会在进入(enter)和离开(leave)阶段,自动添加/移除一组 CSS class,或者触发 JS 钩子。
- Vue 通过过渡状态把“立即插入/移除 DOM”改造成“先过渡,再完成插入/移除”。
- 高频搭配:
v-if:控制挂载和卸载v-show:控制显示和隐藏
1. 它解决的不是“动画”,而是“时机”
如果没有 Transition,v-if 控制的节点通常是:
- 条件为真:直接插入
- 条件为假:直接移除
这意味着节点没有“离场时间”,自然也很难优雅做动画。
Transition 的价值在于:
- 进入时,先挂上进入态 class,再让浏览器执行过渡
- 离开时,不是立刻删 DOM,而是等离场过渡结束再删除
2. 最基本的进入/离开流程
<Transition name="fade">
<div v-if="visible">内容</div>
</Transition>
Vue 会自动管理一组 class:
fade-enter-fromfade-enter-activefade-enter-tofade-leave-fromfade-leave-activefade-leave-to
进入阶段
- 节点准备插入
- 加上
enter-from和enter-active - 下一帧切换到
enter-to - 过渡结束后移除这些 class
离开阶段
- 节点准备离开
- 加上
leave-from和leave-active - 下一帧切换到
leave-to - 等过渡结束后,真正移除 DOM
3. 为什么 Vue 要分 from / active / to?
因为浏览器过渡需要“起点样式”和“终点样式”之间的变化。
例如:
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.fade-enter-to,
.fade-leave-from {
opacity: 1;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
这样浏览器才能从 opacity: 0 平滑过渡到 opacity: 1,反之亦然。
4. v-if 和 v-show 配合时有什么区别?
4.1 配合 v-if
- 控制真实挂载/卸载
- 更适合“组件确实要进场/退场”
4.2 配合 v-show
- 本质是不卸载 DOM,只切换
display - 更适合频繁切换显隐
面试常用总结:
- 切换频繁:优先
v-show - 首屏不一定渲染:优先
v-if
Transition 只是给这两种切换方式都补上了过渡能力。
5. JavaScript 钩子是怎么参与的?
除了 CSS class,Transition 还支持 JS 钩子:
before-enterenterafter-enterbefore-leaveleaveafter-leave
这样你就可以接入:
- GSAP
- anime.js
- 自己写的动画逻辑
如果使用 JS 钩子并显式控制结束时机,Vue 会等待你调用完成回调后再收尾。
6. Transition 的原理可以怎么理解?
从渲染器角度,可以把它看成“在 patch 过程中劫持节点插入和移除”。
简化心智模型:
if (isEnter) {
addEnterClasses(el)
insert(el)
nextFrame(() => switchToEnterTo(el))
whenTransitionEnds(el, cleanupEnterClasses)
}
if (isLeave) {
addLeaveClasses(el)
nextFrame(() => switchToLeaveTo(el))
whenTransitionEnds(el, () => {
remove(el)
cleanupLeaveClasses(el)
})
}
核心点就两句:
- 进入:插入前后插 class
- 离开:延迟删除 DOM,等过渡结束再删
7. 为什么有时动画不生效?
7.1 没有设置 transition 或 animation
加了类名不代表浏览器就会动,CSS 必须定义过渡属性。
7.2 节点没有稳定 key
尤其切换同级元素时,如果没有合适的 key,Vue 可能复用旧节点,过渡时机就不符合预期。
7.3 嵌套动画结束时机不好判断
复杂嵌套场景中,Vue 自动监听到的结束事件可能不是你真正想等的那个,这时需要手动指定 duration。
8. Transition 和 TransitionGroup 区别
Transition:针对单个元素或单个组件切换TransitionGroup:针对列表项的进入、离开、移动
不要把列表过渡全塞给 Transition,这类场景应该用 TransitionGroup。
9. 面试高频答法
Q1:Transition 的原理是什么?
答:本质是在节点进入和离开时,Vue 渲染器不会直接粗暴地插入或移除 DOM,而是先注入一套过渡 class 或调用 JS 钩子,等待过渡结束后再完成 DOM 的最终状态切换。
Q2:v-if 和 v-show 配合 Transition 有什么区别?
答:v-if 是控制节点真实挂载和卸载,适合低频切换;v-show 是保留 DOM、只切换显示状态,适合高频切换。Transition 只是给两者补上过渡时机控制。
速记要点
Transition重点不是动画本身,而是进入/离开的时机控制- 通过
*-enter-*和*-leave-*class 管理状态 - 离开时会延迟移除 DOM,等过渡结束
- 列表场景用
TransitionGroup