You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Router DOM v6.14.0路由切换时如何添加页面动画过渡?

React路由切换平滑过渡实现方法

下面是几种实用的实现方案,可根据项目需求选择:

方案一:React Transition Group + React Router(通用方案)

这是社区常用的组合,通过过渡组件管理路由切换时的动画状态。

  1. 安装依赖
npm install react-transition-group react-router-dom
  1. 配置路由与过渡组件
import { BrowserRouter as Router, Routes, Route, useLocation } from 'react-router-dom';
import { TransitionGroup, CSSTransition } from 'react-transition-group';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';

function AnimatedRoutes() {
  const location = useLocation();

  return (
    <TransitionGroup>
      <CSSTransition
        key={location.key}
        timeout={{ enter: 300, exit: 300 }}
        classNames="page-transition"
        unmountOnExit
      >
        <Routes location={location}>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
          <Route path="/contact" element={<Contact />} />
        </Routes>
      </CSSTransition>
    </TransitionGroup>
  );
}

function App() {
  return (
    <Router>
      <AnimatedRoutes />
    </Router>
  );
}
  1. 编写过渡CSS
/* 进入动画初始状态 */
.page-transition-enter {
  opacity: 0;
  transform: translateX(100%);
}
/* 进入动画执行状态 */
.page-transition-enter-active {
  opacity: 1;
  transform: translateX(0);
  transition: opacity 300ms, transform 300ms;
}
/* 退出动画初始状态 */
.page-transition-exit {
  opacity: 1;
  transform: translateX(0);
}
/* 退出动画执行状态 */
.page-transition-exit-active {
  opacity: 0;
  transform: translateX(-100%);
  transition: opacity 300ms, transform 300ms;
}

方案二:Framer Motion(简洁高效方案)

Framer Motion封装了复杂的动画逻辑,代码更简洁,适合快速实现丰富过渡效果。

  1. 安装依赖
npm install framer-motion react-router-dom
  1. 配置路由与动画
import { BrowserRouter as Router, Routes, Route, useLocation } from 'react-router-dom';
import { AnimatePresence, motion } from 'framer-motion';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';

function AnimatedRoutes() {
  const location = useLocation();

  return (
    <AnimatePresence mode="wait">
      <Routes location={location} key={location.pathname}>
        <Route 
          path="/" 
          element={
            <motion.div
              initial={{ opacity: 0, x: 100 }}
              animate={{ opacity: 1, x: 0 }}
              exit={{ opacity: 0, x: -100 }}
              transition={{ duration: 0.3 }}
            >
              <Home />
            </motion.div>
          } 
        />
        <Route 
          path="/about" 
          element={
            <motion.div
              initial={{ opacity: 0, x: 100 }}
              animate={{ opacity: 1, x: 0 }}
              exit={{ opacity: 0, x: -100 }}
              transition={{ duration: 0.3 }}
            >
              <About />
            </motion.div>
          } 
        />
        <Route 
          path="/contact" 
          element={
            <motion.div
              initial={{ opacity: 0, x: 100 }}
              animate={{ opacity: 1, x: 0 }}
              exit={{ opacity: 0, x: -100 }}
              transition={{ duration: 0.3 }}
            >
              <Contact />
            </motion.div>
          } 
        />
      </Routes>
    </AnimatePresence>
  );
}

方案三:纯CSS + React Router(轻量方案)

无需额外依赖,通过路由切换时的类名变化触发CSS过渡,适合简单的淡入淡出效果。

import { BrowserRouter as Router, Routes, Route, useLocation, useEffect, useState } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';

function AnimatedRoutes() {
  const location = useLocation();
  const [isTransitioning, setIsTransitioning] = useState(false);

  useEffect(() => {
    setIsTransitioning(true);
    const timer = setTimeout(() => setIsTransitioning(false), 300);
    return () => clearTimeout(timer);
  }, [location.pathname]);

  return (
    <div className={`page-container ${isTransitioning ? 'transitioning' : ''}`}>
      <Routes location={location}>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/contact" element={<Contact />} />
      </Routes>
    </div>
  );
}

对应的CSS:

.page-container {
  opacity: 1;
  transition: opacity 300ms ease-in-out;
}
.page-container.transitioning {
  opacity: 0;
}

注意事项

  • 确保路由切换时旧页面不会立即卸载(比如React Transition Group的unmountOnExit、Framer Motion的AnimatePresence需要绑定key)
  • 可根据需求自定义动画类型,比如缩放、旋转等,只需修改CSS或motion组件的参数
  • 嵌套路由场景下,需调整过渡组件的包裹层级,确保仅针对页面级组件触发过渡

内容的提问来源于stack exchange,提问作者Al Amin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 22:15:16