一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

如何解决Vue 3的CSS transition离场失效

时间:2026-09-04 20:49:47 编辑:袖梨 来源:一聚教程网

Vue 3 中 v-leave 类名不触发动画,因其已被重命名为 v-leave-from 作为离场起始状态,若仍沿用 v-leave 或遗漏 -from 后缀,则浏览器无法获取离开起点样式,导致直接卸载 DOM 而无过渡。

为什么v-leave类名不触发动画

Vue 3 的 <Transition> 在离场时依赖 v-leave-from(而非旧版的 v-leave)作为起始状态,但很多人仍按 Vue 2 习惯写 v-leave 或漏掉 -from 后缀,导致浏览器根本没拿到「离开起点」,直接删 DOM。

关键点在于:Vue 3 默认使用 v-leave-from / v-leave-to / v-leave-active 这套命名,且 v-leave-from 必须显式声明初始样式(比如 opacity: 1),否则过渡无起点可插值。

  1. v-leave-fromv-enter-from 都是“变化前”的状态,必须有明确的、非继承的 CSS 值
  2. 若组件内用了 v-if 控制显示,确保它被包裹在 <Transition> 直接子节点中,不能是 v-show
  3. 检查 DevTools 的 Elements 面板 → Computed → 确认 v-leave-from 对应元素的 opacity(或其它过渡属性)是否真为起始值(如 1),而不是 initial 或空

<router-view> 离场动画失效的根源

单纯把 <Transition> 包在 <router-view> 外层,但没用 <keep-alive>,会导致离开的组件在路由切换瞬间被卸载,v-leave-active 还没执行完就被销毁 —— 动画帧被中断。

Vue Router 的 <router-view> 默认不缓存组件实例,v-leave 类刚加上,DOM 就没了。

  1. 必须配合 <keep-alive> 使用:<Transition name="fade"><keep-alive><router-view /></keep-alive></Transition>
  2. 如果用了 v-slot 写法(如 <router-view v-slot="{ Component }">),<Transition> 必须包在 <component :is="Component" /> 外层,且 Component 渲染的必须是单根节点
  3. 避免在 <router-view> 上直接加 v-if,这会干扰 <Transition> 对生命周期的判断

scoped 样式下 v-leave-active 类不生效

<style scoped> 会让 Vue 给选择器自动加 data-v-xxxx 属性,但 <Transition> 运行时动态添加的 v-leave-active 类没有这个哈希,CSS 规则完全不匹配。

这通常不是异常,是 scoped 的设计机制 —— 它只作用于静态编译时的类名,而 transition 类是运行时注入的。

  1. 必须用深度选择器穿透:::v-deep .v-leave-active { transition: opacity 0.3s ease; }
  2. 不要用 /deep/(已在部分构建工具中废弃),优先用 ::v-deep,并确认你的 vue-loader 版本 ≥ 15.9
  3. 如果用了 PostCSS 插件(如 postcss-preset-env),确保没禁用 ::v-deep 解析

组件返回 Fragment 导致离场失败

Vue 3 允许组件模板多根节点(Fragment),但 <Transition> 要求其直接子节点必须是单个 DOM 元素。如果页面组件默认导出的是 <div>...</div><div>...</div>(无外层包装),<Transition> 就无法挂载动画钩子,控制台报错 "non-element root node",离场自然失效。

  1. 每个路由组件的 <template> 必须只返回一个根元素,哪怕只是 <div><!-- 内容 --></div>
  2. 注释、文本节点、空格也算“节点”,<template><!-- 注释 --><div>A</div></template> 是双节点,会失败
  3. 用 DevTools 检查实际渲染的 DOM 结构,确认 <Transition> 下一级是否真只有一个 <div> 或其他原生标签

离场动画最容易被忽略的,是 v-leave-from 的初始值必须和进入时的 v-enter-to 值一致,且不能依赖父级继承或计算值 —— 浏览器只认你写死在 CSS 里的那个数字。

热门栏目