Vue transition 失效的根本原因是过渡系统未触发:transition 必须直接包裹 v-if/v-show 元素,且类名需匹配 scoped 样式(用 :deep 或全局样式),CSS 属性要可动画,动态组件 key 不能频繁变更。

transition 在 Vue 组件切换时没效果,根本原因不是 CSS 写错了,而是 Vue 的过渡系统压根没触发——类名没加到元素上,动画阶段根本没开始。
transition 包裹的元素必须是直接子节点
Vue 的 <transition> 只监听它**紧邻的子元素**的插入/移除。中间插一层 v-show 或 v-if 控制的父容器,就断链了。
- ❌ 错误写法:
<div v-show="showParent"><transition><div v-if="showChild">...</div></transition></div>——<transition>的子节点是<div v-show>,它从不销毁,所以v-enter/v-leave类名永远不会加 - ✅ 正确写法:把
v-if或动态<component>直接放在<transition>里面,且只能有一个根节点 - ⚠️ 注意:如果用了
v-show,它只是切display,DOM 一直存在,<transition>不会响应 —— 必须用v-if
scoped 样式里 .fade-enter-active 类不生效
Vue 的 <transition name="fade"> 添加的类名(如 fade-enter-active)不会带 data-v-xxx 属性,而 <style scoped> 里的规则会被自动加上该属性,导致匹配失败。
- ❌
<style scoped> .fade-enter-active { ... }→ 实际生成的是.fade-enter-active[data-v-abc123] {},但 DOM 上没有这个属性 - ✅ 改用深度选择器:
/deep/ .fade-enter-active(Vue 2)或:deep(.fade-enter-active)(Vue 3) - ? 更推荐:把过渡样式提出来放到全局
<style>中,避开 scoped 限制
动态组件 + key 导致动画跳过
在 <router-view> 或 <component :is="..." :key="..."> 场景下,如果 key 随路由或状态变化,Vue 会强制销毁旧组件、创建新组件,绕过 leave 钩子和过渡流程。
- ❌
<component :is="comp" :key="route.path">→ 每次路由变,key 变,组件被 unmount,v-leave来不及执行 - ✅ 去掉
:key,或固定 key(如:key="'main-view'"),让 Vue 复用组件实例 - ? 如果确实需要 key 控制重渲染,改用
<keep-alive>包裹,再配合<transition>
CSS transition 属性没写对或值不可动画
即使类名加上了,CSS 本身也可能“静音”:
立即学习“前端免费学习笔记(深入)”;
- ❌
height: auto、max-height: none、display: none → block这些都不可过渡 —— 浏览器无法计算中间帧 - ✅ 推荐可动画属性:
opacity、transform、max-height(设具体数值,如max-height: 500px) - ⚠️ 注意:
transition必须写在*-active类里,且要包含具体属性名,比如transition: opacity 0.3s,不能只写transition: all 0.3s(部分浏览器兼容性差)
v-if 嵌套、key 滥用、scoped 样式失配,这些都会让 <transition> 彻底静默。检查时优先打开 DevTools 看元素上有没有 v-enter 类名出现,没有就说明 Vue 过渡系统根本没启动。


















