十一、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. 创建 Home
和 About
组件
jsx
function Home() {
return <h1>首页</h1>;
}
function About() {
return <h1>关于我们</h1>;
}
(四)导航链接 Link
和 NavLink
1. 使用 Link
进行跳转
jsx
import { Link } from "react-router-dom";
function Navbar() {
return (
<nav>
<Link to="/">首页</Link>
<Link to="/about">关于我们</Link>
</nav>
);
}
2. NavLink
(添加选中状态)
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>
);
}
(九)路由重定向
1. 使用 Navigate
组件
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.js
或 router/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;
(二)改进:使用 lazy
和 Suspense
进行按需加载
当页面较多时,可以使用 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;
总结
✅ 单独维护路由表 ,更易管理
✅ 支持嵌套路由 ,减少重复代码
✅ 支持懒加载 ,优化性能
✅ 支持路由守卫,可控访问权限
👉 这样可以让路由更加清晰、解耦,提高可维护性! 🚀