React 路由导航与传参详解
随着单页面应用(SPA)已经成为主流。React 作为最流行的前端框架之一,提供了强大的路由管理工具 react-router-dom
,帮助开发者轻松实现页面导航和传参。本文将详细介绍如何使用 react-router-dom
构建路由导航、传参以及嵌套路由的实现。
1. 构建路由导航
1.1 创建路由实例
在 React 项目中,通常会在 src
目录下创建一个 router
文件夹来管理路由。我们可以使用 react-router-dom
提供的 createBrowserRouter
或 createHashRouter
方法来创建路由实例。
createBrowserRouter
:使用 HTML5 的 history API 来实现路由,URL 看起来更干净,例如:http://example.com/home
。createHashRouter
:使用 URL 的 hash 部分来实现路由,例如:http://example.com/#/home
。
import { createBrowserRouter } from 'react-router-dom';
const router = createBrowserRouter([
{
path: '/',
element: <Home />,
},
{
path: '/login',
element: <Login />,
},
{
path: '/article',
element: <Article />,
},
]);
export default router;
1.2 嵌套路由
在 react-router-dom
中,可以通过 children
属性来配置嵌套路由。嵌套路由允许我们在父路由下定义子路由,从而实现更复杂的页面结构。
const router = createBrowserRouter([
{
path: '/',
element: <Layout />,
children: [
{
path: 'home',
element: <Home />,
},
{
path: 'about',
element: <About />,
},
],
},
]);
1.3 路由导航
在 React 中,有两种主要的方式来实现路由导航:声明式导航 和 编程式导航。
1.3.1 声明式导航
使用 <Link>
组件可以实现声明式导航。<Link>
组件会渲染成一个 <a>
标签,点击后会跳转到指定的路由。
import { Link } from 'react-router-dom';
const Login = () => {
return (
<div>
<h1>登录页</h1>
<Link to="/article">文章页</Link>
</div>
);
};
- 思考:为啥不用a标签?
- a标签每次全部刷新页面,并且需要重新挂载组件,对状态(useState登)需要重置;
每次导航都会重新加载所有资源(如 JavaScript、CSS 等),即使这些资源在前一个页面已经加载过;
无法直接支持动态路由(如 /user/:id); - link标签正好弥补上面缺陷,适合单页面Spa应用。
自动与路由库(如 React Router)集成,支持浏览器的前进和后退功能,同时更新 URL 和历史记录;
只有必要的部分(如新路由对应的组件)会被加载,减少了不必要的网络请求和资源消耗;
点击 组件只会更新当前页面的部分内容(通常是路由对应的组件),而不会重新加载整个页面。这使得无缝地在不同页面之间切换
1.3.2 编程式导航
使用 useNavigate
钩子可以实现编程式导航。useNavigate
返回一个函数,调用该函数并传入目标路径即可实现导航。
import { useNavigate } from 'react-router-dom';
const Login = () => {
const navigate = useNavigate();
return (
<div>
<h1>登录页</h1>
<button onClick={() => navigate('/article')}>文章页</button>
</div>
);
};
2. 路由传参
在 React 路由中,常见的传参方式有两种:searchParams 传参 和 params 传参。
2.1 searchParams 传参
searchParams
传参是通过 URL 的查询字符串来传递参数的。我们可以使用 useSearchParams
钩子来获取和设置查询参数。
import { useNavigate } from 'react-router-dom';
const Login = () => {
const navigate = useNavigate();
return (
<div>
<h1>登录页</h1>
<button onClick={() => navigate('/article?id=1&name=zs')}>
searchParams 传参
</button>
</div>
);
};
在目标组件中,可以使用 useSearchParams
来获取传递的参数:
import { useSearchParams } from 'react-router-dom';
const Article = () => {
const [searchParams] = useSearchParams();
const id = searchParams.get('id');
const name = searchParams.get('name');
return (
<div>
<h1>文章页</h1>
<p>ID: {id}</p>
<p>Name: {name}</p>
</div>
);
};
2.2 params 传参
params
传参是通过 URL 的动态段来传递参数的。首先需要在路由配置中定义动态段,然后在导航时传递参数。
2.2.1 路由配置
const router = createBrowserRouter([
{
path: '/article/:id/:name',
element: <Article />,
},
]);
2.2.2 导航传参
import { useNavigate } from 'react-router-dom';
const Login = () => {
const navigate = useNavigate();
return (
<div>
<h1>登录页</h1>
<button onClick={() => navigate('/article/1001/jack')}>
params 传参
</button>
</div>
);
};
2.2.3 获取参数
在目标组件中,可以使用 useParams
钩子来获取传递的参数:
import { useParams } from 'react-router-dom';
const Article = () => {
const { id, name } = useParams();
return (
<div>
<h1>文章页</h1>
<p>ID: {id}</p>
<p>Name: {name}</p>
</div>
);
};
3. 嵌套路由与 <Outlet />
在嵌套路由中,父路由组件需要使用 <Outlet />
组件作为子路由的占位符。当导航到子路由时,<Outlet />
会被替换为对应的子路由组件。
import { Outlet } from 'react-router-dom';
const Layout = () => {
return (
<div>
<h1>布局页</h1>
<Outlet />
</div>
);
};
在路由配置中,Layout
组件作为父路由,Home
和 About
作为子路由:
const router = createBrowserRouter([
{
path: '/',
element: <Layout />,
children: [
{
path: 'home',
element: <Home />,
},
{
path: 'about',
element: <About />,
},
],
},
]);
4. 重定向与 redirect
参数
在某些场景下,用户可能会尝试访问需要登录的页面,但此时用户尚未登录。为了提升用户体验,我们可以在用户登录后将其重定向回原本想要访问的页面。为了实现这一功能,我们可以在 URL 中添加 redirect
查询参数,记录用户原本想要访问的页面。
4.1 添加 redirect
参数
在用户访问需要登录的页面时,我们可以通过编程式导航将用户重定向到登录页面,并在 URL 中添加 redirect
参数,记录原本要访问的页面。
import { useNavigate } from 'react-router-dom';
const ProtectedPage = () => {
const navigate = useNavigate();
const handleAccess = () => {
const isLoggedIn = false; // 假设用户未登录
if (!isLoggedIn) {
navigate(`/login?redirect=${encodeURIComponent('/protected-page')}`);
}
};
return (
<div>
<h1>受保护的页面</h1>
<button onClick={handleAccess}>访问受保护页面</button>
</div>
);
};
4.2 登录后重定向
在登录页面中,我们可以通过 useSearchParams
获取 redirect
参数,并在用户成功登录后将其重定向回原本想要访问的页面。
import { useSearchParams, useNavigate } from 'react-router-dom';
const Login = () => {
const [searchParams] = useSearchParams();
const navigate = useNavigate();
const redirect = searchParams.get('redirect') || '/';
const handleLogin = () => {
// 假设登录成功
navigate(redirect);
};
return (
<div>
<h1>登录页</h1>
<button onClick={handleLogin}>登录</button>
</div>
);
};
总结
通过 react-router-dom
,我们可以轻松实现 React 应用中的路由导航、传参以及嵌套路由。<Link>
和 useNavigate
提供了灵活的导航方式,而 useSearchParams
和 useParams
则帮助我们处理路由传参。<Outlet />
组件为嵌套路由提供了便捷的占位符功能。此外,通过 redirect
参数,我们可以在用户登录后将其重定向回原本想要访问的页面,从而提升用户体验。掌握这些工具和技巧,能够帮助我们构建更加复杂和高效的单页面应用。