React Router:单页面应用中的路由解决方案
React Router 是 React 生态中最流行的路由解决方案之一,它让单页面应用(SPA)的路由管理变得简单高效。通过 React Router,你可以轻松地管理应用中的不同视图和页面,同时保持用户体验的一致性和流畅性。
一、路由实现的界面效果
导航栏/侧边栏保持不刷新
- 效果:切换路由时,顶部导航、侧边菜单等公共部分保持不动
- 实现 :将共享布局放在父路由的
element
中
js
import { Routes, Route } from 'react-router-dom';
import Layout from './components/Layout';
import Dashboard from './pages/Dashboard';
import Users from './pages/Users';
function App() {
return (
<Routes>
<Route path="/admin" element={<Layout />}>
{/* 子路由内容变化,Layout保持不刷新 */}
<Route index element={<Dashboard />} />
<Route path="users" element={<Users />} />
</Route>
</Routes>
);
}
在这个例子中,Layout
组件包含了导航栏和侧边栏等公共部分。无论用户访问 /admin
还是 /admin/users
,Layout
组件都不会重新渲染,只有其内部的内容会根据子路由的变化而变化。
内容区域动态刷新
- 效果:只有主要内容区域随路由变化
- 实现 :在布局组件中使用
<Outlet />
js
// Layout.js
import { Outlet } from 'react-router-dom';
function Layout() {
return (
<div>
<header>
<h1>My Admin Panel</h1>
<nav>
<ul>
<li><a href="/admin">Dashboard</a></li>
<li><a href="/admin/users">Users</a></li>
</ul>
</nav>
</header>
<main>
<Outlet /> {/* 子路由的内容会在这里渲染 */}
</main>
</div>
);
}
export default Layout;
<Outlet />
是一个占位符,用于渲染当前匹配的子路由的内容。这样,当用户从 /admin
切换到 /admin/users
时,只有 <Outlet />
中的内容会发生变化,而 Layout
组件的其他部分保持不变。
无刷新跳转(保持滚动位置)
- 效果:切换路由时页面不会闪烁,滚动条位置保持不变
- 原理:React Router 默认使用客户端路由(不触发整页刷新)
由于 React Router 使用的是客户端路由,页面不会重新加载,因此滚动位置和其他状态信息会被保留。这使得用户在导航过程中体验更加平滑。
二、路由基本结构
在组件中使用 <Routes>
和 <Route>
定义路由结构:
-
<Routes>
:包裹所有路由规则的容器,负责匹配当前URL并渲染对应的组件 -
<Route>
:定义单个路由规则path
:匹配的URL路径element
:匹配时要渲染的组件index
:标识默认子路由
-
嵌套路由 :通过嵌套
<Route>
实现布局共享
js
import { Routes, Route } from 'react-router-dom';
import Login from './views/login/index';
import MainLayout from './views/layout/index';
import Home from './views/home/index';
import Public from './views/public/index';
import Score from './views/score/index';
function App() {
return (
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/layout" element={<MainLayout />}>
<Route index element={<Home />} />
<Route path="public" element={<Public />} />
<Route path="score" element={<Score />} />
</Route>
</Routes>
);
}
在这个例子中,/layout
路径下的所有子路由都会使用 MainLayout
作为布局组件。具体来说:
- 访问
/layout
时,显示MainLayout
框架 +Home
内容。 - 访问
/layout/public
时,显示MainLayout
框架 +Public
内容。 - 访问
/layout/score
时,显示MainLayout
框架 +Score
内容。
<Route index element={<Home />} />
表示当用户访问 /layout
路径时,默认渲染 Home
组件。
三、useNavigate - 编程式导航
有时候需要在代码逻辑中进行导航,而不是通过点击链接来触发导航。这时可以使用 useNavigate
钩子。
js
import { useNavigate } from 'react-router-dom';
function LoginButton() {
const navigate = useNavigate();
const handleLogin = () => {
// 基本跳转
navigate('/dashboard');
};
return <button onClick={handleLogin}>Login</button>;
}
在这个例子中,当用户点击"Login"按钮时,应用会导航到 /dashboard
路径。 假设当前位置为 http://localhost:3000
,调用 LoginButton
后会自动跳转到 http://localhost:3000/dashboard
。
带参数的导航:
js
import { useNavigate } from 'react-router-dom';
function ProductPage({ productId }) {
const navigate = useNavigate();
const goToProductDetail = () => {
navigate(`/products/${productId}`);
};
return (
<div>
<h1>Product Page</h1>
<button onClick={goToProductDetail}>View Details</button>
</div>
);
}
在这个例子中,navigate
函数可以接受路径参数,从而导航到具体的商品详情页面。请
四、动态路由参数
有时需要在 URL 中传递参数,以便在目标组件中获取这些参数并进行相应的操作。React Router 支持动态路由参数。
定义动态参数:
js
<Route path="/products/:id" element={<ProductDetail />} />
在这个例子中,:id
是一个动态参数,表示产品 ID。
获取动态参数:
js
import { useParams } from 'react-router-dom';
function ProductDetail() {
const { id } = useParams();
// 使用id获取产品数据...
return (
<div>
<h1>Product Detail</h1>
<p>Product ID: {id}</p>
</div>
);
}
在这个例子中,useParams
钩子用于获取 URL 中的动态参数 id
,然后可以在组件中使用这个参数来获取或显示相应的产品数据。