[React] React Router
安装
pnpm i react-router-dom
布局
布局组件用于定义应用程序的整体布局结构,决定如何将匹配的子路由渲染到指定的位置(通过 <Outlet />
)。
file:[src/layouts/index.js]
import { Outlet, Link } from "react-router-dom";
export default function Layout() {
return (
<div>
{/* 导航栏,包含两个链接 */}
<div>
<Link to="/">关于</Link> {/* 导航到主页 */}
<Link to="/board">面板</Link> {/* 导航到面板页面 */}
</div>
{/* 渲染子路由 */}
<div>
<Outlet /> {/* 这里将会渲染匹配的子路由 */}
</div>
</div>
);
}
配置
创建了一个基于哈希的路由配置,其中包含了根路径 /
和其他路径 /login
、/article
的路由规则。根路径下使用 Layout 组件作为布局,包含了默认子路由 /about
和 /board
。其他路径分别对应不同的页面组件。最后,通过 export 将路由实例 router 和路由提供者组件 RouterProvider 导出,以便在应用中使用。
file:[src/router/index.js]
import { createHashRouter, RouterProvider } from "react-router-dom";
import Layout from "../layouts"; // 导入布局组件
import About from "../pages/About"; // 导入关于页面组件
import Board from "../pages/Board"; // 导入面板页面组件
import Login from "../pages/Login"; // 导入登录页面组件
import Article from "../pages/Article"; // 导入文章页面组件
// 创建 hash 路由
const router = createHashRouter([
{
path: "/", // 根路径
// Layout 组件作为根路由的布局
element: <Layout />, // 使用 Layout 组件
children: [
{
index: true, // 当前为根路由的默认子路由
element: <About />, // 渲染关于页面组件
},
{
path: "board", // 面板页面的路径
element: <Board />, // 渲染面板页面组件
},
],
},
{
path: "/login", // 登录页面的路径
element: <Login />, // 渲染登录页面组件
},
{
path: "/article", // 文章页面的路径
element: <Article />, // 渲染文章页面组件
},
]);
export { router, RouterProvider }; // 导出路由和 RouterProvider 组件
使用 <RouterProvider>
组件提供了路由信息给应用,并将 router 路由实例作为参数传递给了 RouterProvider 组件。
file:[src/index.js]
import React from "react";
import ReactDOM from "react-dom/client"; // 引入 ReactDOM 的 createRoot 方法
import "./index.css";
import App from "./App"; // 引入应用主组件
import reportWebVitals from "./reportWebVitals";
import { RouterProvider, router } from "./router"; // 引入路由提供者和路由实例
// 创建根容器
const root = ReactDOM.createRoot(document.getElementById("root")); // 使用 createRoot 方法创建根容器
// 渲染应用
root.render(
<React.StrictMode>
{/* 使用 RouterProvider 提供路由信息给应用 */}
<RouterProvider router={router}>
<App /> {/* 应用主组件 */}
</RouterProvider>
</React.StrictMode>
);
reportWebVitals(); // 上报 Web 性能指标
编程式导航
export default function Layout() {
const navigate = useNavigate();
return (
<div>
<div>
<Link to="/">关于</Link>
<Link to="/board">面板</Link>
add:[<button onClick={() => navigate("/board")}>面板</button>]:add
</div>
<div>
<Outlet />
</div>
</div>
);
}
参数传递
params
file:[src/layouts/index.js]
export default function Layout() {
return (
<div>
<div>
<Link to="/">关于</Link>
<Link to="/board">面板</Link>
add:[<button onClick={() => navigate("/article?id=1001&name=HelloWorld")}>
文章
</button>]:add
</div>
<div>
<Outlet />
</div>
</div>
);
}
file:[src/pages/Article/index.js]
import { useSearchParams } from "react-router-dom";
export default function Article() {
lit:[const [params] = useSearchParams();
console.log(params.get("id"));
console.log(params.get("name"));]:lit
return <div>Article</div>;
}
restful
file:[src/router/index.js]
const router = createHashRouter([
{
// 删除了支持 search params 的路径 "/article"
// 添加了 restful 的路径 "/article/:id/:name"
del:[path: "/article"]:del
add:[path: "/article/:id/:name",]:add
element: <Article />,
},
]);
export { router, RouterProvider };
file:[src/layouts/index.js]
export default function Layout() {
return (
<div>
<div>
<Link to="/">关于</Link>
<Link to="/board">面板</Link>
add:[<button onClick={() => navigate("/article/1001/HelloWorld")}>
文章
</button>]:add
</div>
<div>
<Outlet />
</div>
</div>
);
}
组件通过 useParams 钩子从路由参数中获取 id 和 name 参数。
file:[src/pages/Article/index.js]
import { useParams } from "react-router-dom";
export default function Article() {
lit:[const params = useParams();
console.log(params.id);
console.log(params.name);]:lit
return <div>Article</div>;
}