react 路由使用
一、 BrowserRouter
1. 安装 React Router
npm install react-router-dom
或
yarn add react-router-dom
2. 基础路由配置
(1) 基本结构
在 App.jsx 或入口文件中设置路由:
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import Aboutfrom './pages/About';
import Navbar from './pages/Navbar';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} /> {/* 根路径 首页 */}
<Route path="/about" element={<About/>} /> {/* 关于页*/}
</Routes>
<Navbar />
</BrowserRouter>
)
}
export default App
(2) 导航跳转
使用 <Link> 组件实现无刷新跳转(替代 <a> 标签):
import { Link } from 'react-router-dom';
function Navbar() {
return (
<nav>
<Link to="/">首页</Link> {/* 跳转到根路径 */}
<Link to="/about">关于</Link> {/* 跳转到关于页 */}
</nav>
);
}
3. 动态路由
通过 :param 定义动态参数(如用户ID):
// 路由配置
<Route path="/user/:userId" element={<UserPage />} />
// UserPage 组件中获取参数
import { useParams } from 'react-router-dom';
function UserPage() {
const { userId } = useParams(); // 获取动态参数
return <div>用户ID: {userId}</div>;
}
4. 嵌套路由
父路由下定义子路由,需用 <Outlet> 作为子路由的渲染出口:
// 父路由配置
<Route path="/dashboard" element={<Dashboard />}>
<Route path="stats" element={<Stats />} /> {/* /dashboard/stats */}
<Route path="settings" element={<Settings />} /> {/* /dashboard/settings */}
</Route>
// Dashboard 组件中放置 <Outlet>
function Dashboard() {
return (
<div>
<h1>仪表盘</h1>
<Outlet /> {/* 子路由内容在此渲染 */}
</div>
);
}
5. 编程式导航
通过 useNavigate Hook 实现代码跳转(如登录后跳转):
import { useNavigate } from 'react-router-dom';
function LoginButton() {
const navigate = useNavigate();
const handleLogin = () => {
// 模拟登录逻辑...
navigate('/dashboard'); // 跳转到仪表盘
};
return <button onClick={handleLogin}>登录</button>;
}
6. 路由守卫(权限控制)
通过高阶组件或包装组件实现登录验证:
// PrivateRoute 组件
import { Navigate } from 'react-router-dom';
function PrivateRoute({ children }) {
const isAuthenticated = true; // 替换为实际登录状态判断
return isAuthenticated ? children : <Navigate to="/login" replace />;
}
// 使用方式
<Route
path="/admin"
element={<PrivateRoute><AdminPage /></PrivateRoute>}
/>
7. 404 页面处理
捕获所有未匹配的路由:
<Route path="*" element={<NotFoundPage />} /> {/* 404 页面 */}
8. 路由懒加载(代码分割)
结合 React.lazy 和 Suspense 实现按需加载:
import { lazy, Suspense } from 'react';
const LazyAbout = lazy(() => import('./pages/About'));
function App() {
return (
<BrowserRouter>
<Suspense fallback={<div>加载中...</div>}>
<Routes>
<Route path="/about" element={<LazyAbout />} />
</Routes>
</Suspense>
</BrowserRouter>
);
}
9. 路由模式
- BrowserRouter:基于 HTML5 History API(推荐,URL 无
#)。 - HashRouter:URL 带
#(兼容旧服务器)。
import { HashRouter } from 'react-router-dom';
<HashRouter>...</HashRouter>
10. 常见问题
(1) 刷新页面后路由丢失?
- 确保服务器配置了 SPA 回退(如 Nginx 的
try_files或 Netlify 的_redirects)。 - 示例 Nginx 配置:
location / { try_files $uri $uri/ /index.html; }
(2) 如何传递状态给路由组件?
使用 state 属性:
<Link to="/about" state={{ from: 'home' }}>关于</Link>
// About 组件中获取状态
import { useLocation } from 'react-router-dom';
const { state } = useLocation(); // { from: 'home' }
总结
| 功能 | 关键 API/组件 |
|---|---|
| 路由配置 | BrowserRouter, Routes, Route |
| 导航跳转 | <Link>, useNavigate |
| 动态路由 | :param, useParams |
| 嵌套路由 | <Outlet> |
| 权限控制 | Navigate, 高阶组件 |
| 懒加载 | React.lazy, Suspense |
通过 React Router,你可以轻松实现复杂的单页应用(SPA)路由需求!
二、createBrowserRouter
import { createBrowserRouter } from 'react-router-dom';
import Home from '../pages/Home';
import Video from '../pages/Video';
// 创建路由配置
const router = createBrowserRouter(
[
{
path: '/',
element: <Home />,
},
{
path: '/video',
element: <Video />,
},
],
{
basename: '', // ✅ 如果你的 base 是 './',这里设为空字符串
}
);
export default router;
1. createBrowserRouter(...)
这是 React Router v6.4+ 提供的一个 工厂函数,用于 创建一个路由器实例(Router Object),它是 新一代更灵活、更强大路由配置方式的核心。
它接收两个参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| 第一个参数 | RouteObject[] |
路由配置数组,每个对象定义一条路由规则,包括 path 和 element 等 |
| 第二个参数 | RouterOptions |
可选的配置项,比如 basename、future 等 |
2. 路由配置数组(RouteObject[])
[
{ path: '/', element: <Home /> },
{ path: '/video', element: <Video /> },
// ...其他路由
]
每一项是一个 路由对象(RouteObject),包含:
| 属性 | 说明 |
|---|---|
path |
当前路由的路径,比如 '/', '/video' |
element |
对应这个路径要渲染的 React 组件(必须是 JSX 元素,比如 <Home />) |
⚠️ 注意:这里的
<Home />等组件需要 提前导入,比如:import Home from './pages/Home'; import Video from './pages/Video'; // 以此类推
3. 配置项 { basename: '' }
basename是部署应用时使用的 基础路径前缀。- 比如,如果你的应用不是部署在网站根目录
/,而是部署在/app/子路径下,那么你需要设置:basename: '/app' - 如果你的应用部署在网站根目录,或者 Vite 的
base: './',那么通常设为:basename: '' // 或者 basename: '/' - 你这里设为
''是没问题的,表示路由匹配的是相对根路径的。
🧩 二、如何使用这个 router 对象?
你定义了 router,但 它本身不会自动生效,你还需要在应用的顶层使用一个 Router Provider 来激活路由功能。
✅ 正确用法:配合 <RouterProvider router={router} />
在你的 App.tsx(或入口组件)中,你应该这样使用:
// App.tsx
import { RouterProvider } from 'react-router-dom';
import router from './router'; // 假设你把上面的 router 定义放在了 src/router/index.tsx
import Navbar from './components/Navbar';
function App() {
return (
<>
{/* 路由视图容器 */}
<div className='main'>
<RouterProvider router={router} /> {/* ✅ 这里启用路由 */}
</div>
{/* 如果有固定的导航栏、底部栏,可以放在路由外面 */}
<Navbar />
</>
);
}
export default App;
✅ 注意:
<RouterProvider router={router} />是必须的!它会把路由上下文注入到 React Tree 中,这样<Routes>和<Route>或者 hooks(如useNavigate)才能正常工作。
🧩 三、这个路由方式的特点与优势
✅ 1. 更灵活、可抽离的路由配置
- 你可以把所有路由规则集中管理(比如在
src/router/index.tsx),便于维护和扩展。 - 支持嵌套路由、动态路由、懒加载等高级功能(后续可扩展)。
✅ 2. 使用 createBrowserRouter + RouterProvider 是 React Router v6.4+ 推荐的方式
- 相比旧版的
<BrowserRouter><Routes>...</Routes></BrowserRouter>写法,这种新方式更模块化,更适合大型项目。 - 特别适合配合 数据加载、布局路由、嵌套路由 等高级功能。
✅ 3. 支持 basename、未来特性配置
- 比如你可以设置
basename: '/app'来支持子路径部署。 - 也可以通过
future配置启用实验性功能。
🧩 四、对比传统写法(你可能之前用的)
❓ 你可能之前是这样写的(传统写法):
// App.tsx
import { BrowserRouter, Routes, Route } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/video" element={<Video />} />
{/* 其它 Route */}
</Routes>
</BrowserRouter>
);
}
🔁 对应到新写法就是:
<BrowserRouter>→ 由createBrowserRouter(...)创建的router对象代替<Routes><Route>→ 被抽离到路由配置数组中,作为route objects- 整个路由系统由
<RouterProvider router={router} />激活
🧩 五、如何扩展?(未来你可以这样做)
✅ 嵌套路由
你可以在路由配置里使用 children 来定义子路由。
✅ 布局路由(Layout)
通过定义带有 <Outlet /> 的布局组件,实现统一 UI 布局(比如统一的 Header / Footer)。
✅ 懒加载路由
结合 React.lazy() 和 Suspense,实现路由组件的按需加载,优化性能。
✅ 路由数据加载(Loader)
在 v6.4+ 中还可以为路由定义 loader 函数,在进入路由前加载数据(类似 Next.js 的 getServerSideProps)。
✅ 总结:你这种路由方式如何使用?
1. 定义路由配置
// src/router/index.tsx
import { createBrowserRouter } from 'react-router-dom';
import Home from '../pages/Home';
import Video from '../pages/Video';
// ... 其它组件导入
const router = createBrowserRouter(
[
{ path: '/', element: <Home /> },
{ path: '/video', element: <Video /> },
// 其它路由
],
{ basename: '' }
);
export default router;
2. 在 App.tsx 中使用 RouterProvider 启用路由
// App.tsx
import { RouterProvider } from 'react-router-dom';
import router from './router';
import Navbar from './components/Navbar';
function App() {
return (
<>
<div className='main'>
<RouterProvider router={router} /> {/* ✅ 启用路由系统 */}
</div>
<Navbar /> {/* 静态导航,放在路由外 */}
</>
);
}
export default App;
3. 访问页面
- 打开
/→ 渲染<Home /> - 打开
/video→ 渲染<Video /> - 以此类推
✅ 最终推荐做法(结构清晰、可扩展)
src/
├── App.tsx
├── main.tsx
├── router/
│ └── index.tsx // 路由配置集中管理
├── pages/
│ ├── Home.tsx
│ ├── Video.tsx
│ ├── Message.tsx
│ ├── Shopping.tsx
│ └── My.tsx
└── components/
└── Navbar.tsx
❗注意事项
| 注意事项 | 说明 |
|---|---|
✅ 必须用 <RouterProvider router={router} /> 包裹,否则路由上下文不存在,会报错 |
比如 useNavigate() 或 <Routes> 无法工作 |
✅ 不要同时使用 <BrowserRouter> 和 RouterProvider |
只选其中一种方式 |
✅ 确保所有 element: <Component /> 中的组件已正确导入 |
否则会报错 ReferenceError |
✅ basename 通常设为 '' 或 '/',除非你部署在子路径下 |
比如 /app/ 则设为 basename: '/app' |
三,路由跳转
一、使用 useNavigate() 进行编程式导航(推荐)
这是 最常用、最灵活的路由跳转方式,适用于按钮点击、表单提交后跳转、条件跳转等场景。
🧩 1. 基本用法
步骤:
- **在组件中引入
useNavigate** - 调用
navigate(path)进行跳转
✅ 示例代码
// src/pages/SomePage.tsx
import { useNavigate } from 'react-router-dom';
function SomePage() {
const navigate = useNavigate();
const handleClick = () => {
// 跳转到 /video 页面
navigate('/video');
};
return (
<div>
<h1>这是某个页面</h1>
<button onClick={handleClick}>跳转到视频页</button>
</div>
);
}
export default SomePage;
✅ 可选参数
navigate 函数还可以接收 第二个参数,是一个对象,用于控制跳转行为:
navigate('/video', {
replace: true, // 替换当前历史记录,而不是新增(用户点击后退不会回到这个页面)
state: { from: 'home' } // 传递状态数据(可在目标页面通过 useLocation().state 获取)
});
示例:
navigate('/video', { replace: true });
// 或者带状态
navigate('/video', { state: { id: 123, from: 'home' } });
✅ 二、使用 <Link> 组件进行声明式导航(类似 <a> 标签)
如果你想实现 类似普通超链接的导航(用户点击即可跳转,无 JS 交互逻辑),可以使用 React Router 提供的 <Link> 组件。
🧩 用法:
import { Link } from 'react-router-dom';
function NavBar() {
return (
<nav>
<Link to="/">首页</Link>
<Link to="/video">视频</Link>
<Link to="/message">消息</Link>
<Link to="/shopping">购物</Link>
<Link to="/my">我的</Link>
</nav>
);
}
✅ 特点:
- 点击后无刷新跳转(单页应用 SPA 特性)。
- 支持
to属性,值可以是字符串路径,如to="/video"。 - 也可以传对象,比如带查询参数或状态:
<Link to={{ pathname: '/video', search: '?t=123', state: { from: 'home' } }} />
✅ 三、在你的实际项目结构中如何组织?
假设你的路由配置是这样的(使用 <RouterProvider> 方式):
// src/router/index.tsx
import { createBrowserRouter } from 'react-router-dom';
import Home from '../pages/Home';
import Video from '../pages/Video';
import Message from '../pages/Message';
import Shopping from '../pages/Shopping';
import My from '../pages/My';
const router = createBrowserRouter([
{ path: '/', element: <Home /> },
{ path: '/video', element: <Video /> },
{ path: '/message', element: <Message /> },
{ path: '/shopping', element: <Shopping /> },
{ path: '/my', element: <My /> },
]);
export default router;
然后在 App.tsx 中使用:
// App.tsx
import { RouterProvider } from 'react-router-dom';
import router from './router';
import Navbar from './components/Navbar';
function App() {
return (
<>
<div className='main'>
<RouterProvider router={router} /> {/* ✅ 路由系统启动 */}
</div>
<Navbar /> {/* 导航栏,可以放<Link>或按钮跳转逻辑 */}
</>
);
}
export default App;
✅ 四、总结:路由跳转的 2 种主要方式
| 方式 | 用法 | 适用场景 | 是否需要导入 |
|---|---|---|---|
**1. useNavigate()** |
编程式导航,调用 navigate('/path') |
按钮点击跳转、条件跳转、表单提交后跳转等 | import { useNavigate } from 'react-router-dom' |
**2. <Link to="/path">** |
声明式导航,类似 <a> 标签 |
导航栏、菜单、静态链接等 | import { Link } from 'react-router-dom' |
✅ 五、额外提示
1. **<Link> 不会引起页面刷新!**
- 它是通过 History API 实现的单页跳转(SPA),和普通
<a href="/video">不一样,不会导致整页重新加载。
2. 在路由之间传递数据
- 通过 URL 参数(动态路由):比如
/video/123→ 可用useParams()获取123 - 通过查询参数(search):比如
/video?t=123→ 可用useSearchParams()解析 - 通过状态(state):
navigate('/video', { state: { from: 'home' } })→ 可用useLocation().state获取
✅ 六、完整示例:跳转按钮 + 导航菜单
1. 组件内跳转(编程式,使用 useNavigate)
// src/pages/Home.tsx
import { useNavigate } from 'react-router-dom';
function Home() {
const navigate = useNavigate();
return (
<div>
<h1>首页</h1>
<button onClick={() => navigate('/video')}>去看视频</button>
</div>
);
}
2. 导航栏跳转(声明式,使用 <Link>)
// src/components/Navbar.tsx
import { Link } from 'react-router-dom';
function Navbar() {
return (
<nav>
<Link to="/">首页</Link> |
<Link to="/video">视频</Link> |
<Link to="/message">消息</Link> |
<Link to="/shopping">购物</Link> |
<Link to="/my">我的</Link>
</nav>
);
}
export default Navbar;
✅ 总结一句话
当你使用 **
<RouterProvider router={router} />**(React Router v6.4+ 的推荐方式)时,你仍然可以使用:
- **
useNavigate() 进行 编程式导航(如按钮跳转)**- **
<Link to="..."> 进行 声明式导航(如菜单链接)**
这两种方式是 React Router 中实现路由跳转的 标准、推荐且最常用的方法,无论你的路由配置是通过 <BrowserRouter> 还是 RouterProvider 管理,它们都能完美工作!
更多推荐
所有评论(0)