一、react-router6 安装配置
1.1 安装
npm install react-router-dom@6
1.2 数据路由 API(v6.4+ 推荐)
// src/router/index.jsx
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Home from "@/pages/Home";
import About from "@/pages/About";
const router = createBrowserRouter([
{ path: "/", element: <Home /> },
{ path: "/about", element: <About /> },
]);
// main.jsx
import { RouterProvider } from "react-router-dom";
import router from "./router";
createRoot(document.getElementById("root")).render(
<RouterProvider router={router} />
);
1.3 组件式写法(兼容老习惯)
import { BrowserRouter, Routes, Route } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</BrowserRouter>
);
}
v6 相比 v5 的核心变化:
Switch→Routes、component→element、路由匹配从"全部匹配"变为"排名匹配"。
二、声明式 / 编程式导航
2.1 声明式:Link / NavLink
import { Link, NavLink } from "react-router-dom";
<Link to="/about">关于</Link>
<Link to={`/detail/${id}`}>详情</Link>
{/* NavLink:当前路由自动加 active 类 */}
<NavLink to="/" className={({ isActive }) => (isActive ? "active" : "")}>首页</NavLink>
2.2 编程式:useNavigate
import { useNavigate } from "react-router-dom";
function LoginBtn() {
const navigate = useNavigate();
const goLogin = () => navigate("/login"); // 跳转
const replace = () => navigate("/home", { replace: true }); // 替换不留历史
const back = () => navigate(-1); // 后退
return <button onClick={goLogin}>去登录</button>;
}
三、useParams / useSearchParams 传参
3.1 路径参数:useParams
// 路由声明
{ path: "/detail/:id", element: <Detail /> }
// 组件内读取
import { useParams } from "react-router-dom";
function Detail() {
const { id } = useParams(); // URL:/detail/10 → id = "10"
return <p>详情 ID:{id}</p>;
}
3.2 查询参数:useSearchParams
// 跳转带 query
navigate(`/list?page=2&keyword=react`);
// 组件内读取与修改
import { useSearchParams } from "react-router-dom";
function List() {
const [searchParams, setSearchParams] = useSearchParams();
const page = searchParams.get("page") || "1";
const nextPage = () => {
setSearchParams({ page: Number(page) + 1, keyword: searchParams.get("keyword") ?? "" });
};
return <button onClick={nextPage}>第 {page} 页 → 下一页</button>;
}
3.3 两种传参对比
| 对比项 | 路径参数 useParams | 查询参数 useSearchParams |
|---|---|---|
| URL 形态 | /detail/10 | /list?page=2 |
| 读取 | useParams() | useSearchParams().get() |
| 刷新 | 不丢 | 不丢(都在 URL) |
| 适用 | 资源标识(id) | 筛选、分页、搜索条件 |
四、父子组件通信
4.1 父传子:props
function Parent() {
const [count, setCount] = useState(0);
return <Child count={count} onAdd={() => setCount(count + 1)} />;
}
4.2 子传父:回调函数
function Child({ count, onAdd }) {
return (
<div>
<p>计数:{count}</p>
<button onClick={onAdd}>+1</button> {/* 调用父组件传入的回调 */}
</div>
);
}
React 无自定义事件:父传子用 props,子传父用回调(等价于 Vue 的 $emit)。
五、跨层通信:useContext
解决"祖先 → 任意后代"的共享数据(主题、登录态、语言等),免去逐层传 props。
5.1 创建与提供
// context/AuthContext.js
import { createContext, useContext, useState } from "react";
const AuthContext = createContext(null);
// Provider:包裹需要共享的子树
export function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const login = (u) => setUser(u);
const logout = () => setUser(null);
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
}
// 自定义 Hook:方便使用
export function useAuth() {
return useContext(AuthContext);
}
5.2 使用
// main.jsx 根部包裹
<AuthProvider>
<RouterProvider router={router} />
</AuthProvider>
// 任意后代组件
function Profile() {
const { user, logout } = useAuth();
if (!user) return <p>未登录</p>;
return <button onClick={logout}>{user.name} - 退出</button>;
}
注意:Context 值变化会让所有消费组件重渲染;高频变化的状态建议拆分 Context 或配合 useMemo 稳定 value。
六、路由嵌套、404、重定向
6.1 嵌套路由:Outlet
const router = createBrowserRouter([
{
path: "/user",
element: <UserLayout />, // 父布局
children: [
{ index: true, element: <UserProfile /> }, // /user 默认子路由
{ path: "orders", element: <UserOrders /> }, // /user/orders
],
},
]);
// UserLayout.jsx:子路由出口
import { Outlet, NavLink } from "react-router-dom";
export default function UserLayout() {
return (
<div>
<nav>
<NavLink to="/user">资料</NavLink>
<NavLink to="/user/orders">订单</NavLink>
</nav>
<Outlet /> {/* 子路由组件渲染位置 */}
</div>
);
}
6.2 重定向与 404
import { Navigate } from "react-router-dom";
const router = createBrowserRouter([
{ path: "/", element: <Navigate to="/home" replace /> }, // 重定向
// 404 兜底(放最后)
{ path: "*", element: <NotFound /> },
]);
6.3 路由守卫(登录鉴权)
function RequireAuth({ children }) {
const { user } = useAuth();
if (!user) {
return <Navigate to="/login" replace />; // 未登录跳登录页
}
return children;
}
const router = createBrowserRouter([
{
path: "/admin",
element: (
<RequireAuth>
<AdminLayout />
</RequireAuth>
),
},
]);
七、总结
- 配置:
createBrowserRouter+RouterProvider,Routes/Route组件式二选一; - 导航:
Link/NavLink声明式、useNavigate编程式; - 传参:路径参数
useParams(资源 id)、查询参数useSearchParams(筛选分页),都在 URL 中刷新不丢; - 通信:父传子 props、子传父回调、跨层
useContext(createContext + Provider + useAuth); - 路由进阶:
Outlet嵌套、Navigate重定向、path="*"兜底 404、RequireAuth包裹实现鉴权。