核心是用状态类名(如.page-enter-active/.page-leave-active)控制动画触发,配合animation-fill-mode: both、仅用opacity/transform等高性能属性,并严格管理类名增删时机与层叠上下文。
animation 实现页面切换动画核心是「状态类名控制动画触发」,不是靠 JS 直接调用 animate() 或操作 keyframes。浏览器对 class 切换的重绘更可控,也更容易和路由、组件生命周期对齐。
常见错误是把动画写在初始样式里(比如直接给 .page 加 animation),结果一进页面就播,无法响应「进入/离开」两个方向。
.page-enter-active、.page-leave-active
.page-enter → .page-enter-active,离开时加 .page-leave → .page-leave-active
animation-fill-mode: both,否则动画结束瞬间样式会回退到初始值(比如 opacity 突然变 1)@keyframes 里不要写 layout 触发属性像 height、top、left 这类会触发 Layout 的属性,在动画中会导致卡顿,尤其在低端设备或复杂 DOM 下。
优先用只触发 Composite 的属性:opacity、transform(translateX、scale、rotate)。
@keyframes slideInRight {
from {
opacity: 0;
transform: translateX(100%);
}
to {
opacity: 1;
transform: translateX(0);
}
}
.page-enter-active {
animation: slideInRight 0.3s ease-out;
animation-fill-mode: both;
}
当路由快速切换(比如连点两次导航),旧页面还没走完 leave 动画,新页面就进来了,容易出现层叠、错位、z-index 混乱。
position: relative 和统一 z-index,再用 transform: translateZ(0) 强制生成新层叠上下文.page-leave-active 类(CSS 不会自动清理).page-enter-active,可用 getComputedStyle(el).animationName 检查是否还在播不能等组件 mounted 或 useEffect 才加类 —— 那时 DOM 已渲染完毕,动画会漏掉第一帧。
正确做法是在「决定切换」的瞬间(如点击导航后、路由解析完成时)立刻添加 enter/leave 类,再让框架更新 DOM。
的 enter-from-class/leave-to-class 配合 appear,别手写 class 切换逻辑useLayoutEffect 在 DOM 绘制前加类,比 useEffect 更稳popstate 后立即操作 class,然后用 requestAnimationFrame 延迟一帧再更新内容