【前端】【React】第四章:深入理解 React Router 及前端路由管理

十一、React Router 及前端路由管理

React 是一个单页面应用(SPA)框架,通常使用 React Router 进行路由管理。React Router 提供 客户端路由,避免页面刷新,提高用户体验。


(一)React Router 基本概念

React Router 采用 基于组件的路由,核心概念包括:

术语 作用
BrowserRouter 使应用支持 HTML5 History API 的路由
Routes 用于包裹所有 Route 组件
Route 定义 URL 与组件的映射关系
Link / NavLink 生成前端导航链接
useNavigate 编程式导航,替代 history.push
useParams 获取 URL 动态参数
useLocation 获取当前 URL 信息

(二)安装 React Router

sh 复制代码
npm install react-router-dom

(三)基本路由配置

1. 创建路由
jsx 复制代码
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./Home";
import About from "./About";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;
2. 创建 HomeAbout 组件
jsx 复制代码
function Home() {
  return <h1>首页</h1>;
}

function About() {
  return <h1>关于我们</h1>;
}

jsx 复制代码
import { Link } from "react-router-dom";

function Navbar() {
  return (
    <nav>
      <Link to="/">首页</Link>
      <Link to="/about">关于我们</Link>
    </nav>
  );
}
jsx 复制代码
import { NavLink } from "react-router-dom";

function Navbar() {
  return (
    <nav>
      <NavLink to="/" style={({ isActive }) => ({ color: isActive ? "red" : "black" })}>
        首页
      </NavLink>
      <NavLink to="/about">关于我们</NavLink>
    </nav>
  );
}

(五)动态路由与参数 useParams

1. 定义动态路由
jsx 复制代码
<Routes>
  <Route path="/user/:id" element={<User />} />
</Routes>
2. 获取路由参数
jsx 复制代码
import { useParams } from "react-router-dom";

function User() {
  const { id } = useParams();
  return <h1>用户 ID: {id}</h1>;
}

(六)编程式导航 useNavigate

1. 跳转到指定页面
jsx 复制代码
import { useNavigate } from "react-router-dom";

function Home() {
  const navigate = useNavigate();

  return (
    <div>
      <h1>首页</h1>
      <button onClick={() => navigate("/about")}>跳转到关于页</button>
    </div>
  );
}
2. 传递参数
jsx 复制代码
navigate("/user/123");

(七)获取当前路由 useLocation

jsx 复制代码
import { useLocation } from "react-router-dom";

function CurrentRoute() {
  const location = useLocation();
  return <h1>当前路径: {location.pathname}</h1>;
}

(八)嵌套路由(子路由)

1. 定义子路由
jsx 复制代码
<Routes>
  <Route path="/dashboard" element={<Dashboard />}>
    <Route path="profile" element={<Profile />} />
    <Route path="settings" element={<Settings />} />
  </Route>
</Routes>
2. Dashboard 组件中渲染子组件
jsx 复制代码
import { Outlet } from "react-router-dom";

function Dashboard() {
  return (
    <div>
      <h1>仪表盘</h1>
      <Outlet />
    </div>
  );
}

(九)路由重定向

jsx 复制代码
import { Navigate } from "react-router-dom";

function NotFound() {
  return <Navigate to="/" />;
}

(十)路由守卫(权限控制)

1. 创建 ProtectedRoute 组件
jsx 复制代码
import { Navigate } from "react-router-dom";

function ProtectedRoute({ isAuth, children }) {
  return isAuth ? children : <Navigate to="/login" />;
}
2. 使用路由守卫
jsx 复制代码
<Route path="/dashboard" element={<ProtectedRoute isAuth={isLoggedIn}><Dashboard /></ProtectedRoute>} />

十二、总结

1. React Router 核心概念

术语 作用
Routes / Route 定义路由
Link / NavLink 导航链接
useNavigate 编程式跳转
useParams 获取动态参数
useLocation 获取当前 URL
Navigate 进行路由重定向
Outlet 处理嵌套路由

2. 路由功能

  • 基本路由<Route path="/" element={<Home />} />
  • 动态路由<Route path="/user/:id" element={<User />} />
  • 导航链接<Link to="/about">关于我们</Link>
  • 编程式导航navigate("/dashboard")
  • 嵌套路由<Outlet />
  • 路由重定向<Navigate to="/" />
  • 路由守卫 :封装 <ProtectedRoute> 组件

在大型 React 应用中,单独维护路由表 是一种更好的实践,可以提高可读性、可维护性和复用性。通常,开发者会在 routes.jsrouter/index.js 文件中集中管理路由。


(一)使用独立路由表

1. 创建 routes.js

jsx 复制代码
// routes.js
import Home from "./pages/Home";
import About from "./pages/About";
import Dashboard from "./pages/Dashboard";
import Profile from "./pages/Profile";
import Settings from "./pages/Settings";
import NotFound from "./pages/NotFound";

const routes = [
  { path: "/", element: <Home /> },
  { path: "/about", element: <About /> },
  {
    path: "/dashboard",
    element: <Dashboard />,
    children: [
      { path: "profile", element: <Profile /> },
      { path: "settings", element: <Settings /> },
    ],
  },
  { path: "*", element: <NotFound /> },
];

export default routes;

2. App.js 里引入并渲染

jsx 复制代码
// App.js
import { BrowserRouter, Routes, Route } from "react-router-dom";
import routes from "./routes";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        {routes.map(({ path, element, children }) => (
          <Route key={path} path={path} element={element}>
            {children &&
              children.map((child) => (
                <Route key={child.path} path={child.path} element={child.element} />
              ))}
          </Route>
        ))}
      </Routes>
    </BrowserRouter>
  );
}

export default App;

(二)改进:使用 lazySuspense 进行按需加载

当页面较多时,可以使用 React.lazy 进行 按需加载(懒加载),减少首屏加载时间。

1. 修改 routes.js

jsx 复制代码
import { lazy } from "react";

const Home = lazy(() => import("./pages/Home"));
const About = lazy(() => import("./pages/About"));
const Dashboard = lazy(() => import("./pages/Dashboard"));
const Profile = lazy(() => import("./pages/Profile"));
const Settings = lazy(() => import("./pages/Settings"));
const NotFound = lazy(() => import("./pages/NotFound"));

const routes = [
  { path: "/", element: <Home /> },
  { path: "/about", element: <About /> },
  {
    path: "/dashboard",
    element: <Dashboard />,
    children: [
      { path: "profile", element: <Profile /> },
      { path: "settings", element: <Settings /> },
    ],
  },
  { path: "*", element: <NotFound /> },
];

export default routes;

2. App.js 里添加 Suspense

jsx 复制代码
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { Suspense } from "react";
import routes from "./routes";

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<div>加载中...</div>}>
        <Routes>
          {routes.map(({ path, element, children }) => (
            <Route key={path} path={path} element={element}>
              {children &&
                children.map((child) => (
                  <Route key={child.path} path={child.path} element={child.element} />
                ))}
            </Route>
          ))}
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

export default App;

(三)结合路由守卫

routes.js 里可以添加 权限控制 ,通过 meta.auth 判断是否需要登录:

1. 修改 routes.js

jsx 复制代码
import { lazy } from "react";
import ProtectedRoute from "./components/ProtectedRoute";

const Home = lazy(() => import("./pages/Home"));
const About = lazy(() => import("./pages/About"));
const Dashboard = lazy(() => import("./pages/Dashboard"));
const Login = lazy(() => import("./pages/Login"));

const routes = [
  { path: "/", element: <Home /> },
  { path: "/about", element: <About /> },
  {
    path: "/dashboard",
    element: <ProtectedRoute><Dashboard /></ProtectedRoute>,
    meta: { auth: true }, // 需要登录
  },
  { path: "/login", element: <Login /> },
];

export default routes;

2. 创建 ProtectedRoute.js

jsx 复制代码
import { Navigate } from "react-router-dom";

function ProtectedRoute({ children }) {
  const isLoggedIn = localStorage.getItem("token"); // 模拟鉴权
  return isLoggedIn ? children : <Navigate to="/login" />;
}

export default ProtectedRoute;

总结

单独维护路由表 ,更易管理

支持嵌套路由 ,减少重复代码

支持懒加载 ,优化性能

支持路由守卫,可控访问权限

👉 这样可以让路由更加清晰、解耦,提高可维护性! 🚀

下一章:React 状态管理(Context API、Redux、Zustand) 🚀

相关推荐
qq. 28040339842 小时前
CSS层叠顺序
前端·css
喝拿铁写前端3 小时前
SmartField AI:让每个字段都找到归属!
前端·算法
猫猫不是喵喵.3 小时前
vue 路由
前端·javascript·vue.js
烛阴3 小时前
JavaScript Import/Export:告别混乱,拥抱模块化!
前端·javascript
bin91533 小时前
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加行拖拽排序功能示例12,TableView16_12 拖拽动画示例
前端·javascript·vue.js·ecmascript·deepseek
GISer_Jing4 小时前
[Html]overflow: auto 失效原因,flex 1却未设置min-height &overflow的几个属性以及应用场景
前端·html
程序员黄同学4 小时前
解释 Webpack 中的模块打包机制,如何配置 Webpack 进行项目构建?
前端·webpack·node.js
拉不动的猪4 小时前
vue自定义“权限控制”指令
前端·javascript·vue.js
再学一点就睡4 小时前
浏览器页面渲染机制深度解析:从构建 DOM 到 transform 高效渲染的底层逻辑
前端·css
拉不动的猪4 小时前
刷刷题48 (setState常规问答)
前端·react.js·面试