前言
在单页面应用(SPA)开发中,前端路由是核心基石。它让我们可以根据 URL 的变化,在不刷新页面的情况下切换组件。本文将带你从 React Router 的基本使用出发,深入其底层的浏览器实现机制。
一、 React 路由配置实战
1. 基础环境搭建
首先,我们需要安装 React 路由的核心库:
npm install react-router-dom
2. 注入路由容器
需要在应用最顶层(如 main.jsx/App.jsx)包裹路由核心容器,决定使用 Hash 模式 还是 History 模式,二者的核心区别是 URL 是否带 #,以及服务端配置要求。
两种模式核心区别:
| 特性 | History 模式 | Hash 模式 |
|---|---|---|
| URL 形式 | https://xxx.com/home(无 #) | https://xxx.com/#/home(带 #) |
| 服务端配置 | 需要 Nginx配置兜底 | 无需服务端配置 |
| 兼容性 | 依赖 HTML5 History API | 兼容所有浏览器 |
| 场景 | =现代浏览器 | 老项目兼容 |
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter, HashRouter } from 'react-router-dom';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
// 方式1:History 模式(推荐,URL 无 #,美观)
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);
// 方式2:Hash 模式(兼容老浏览器/无需后端配置,URL 带 #)
// root.render(
// <HashRouter>
// <App />
// </HashRouter>
// );
3. 定义路由映射
通过 <Routes> 和 <Route> 定义「URL 路径 → 组件」的映射关系,用 <Link> 替代原生 <a> 标签实现无刷新导航。
import { Routes, Route, Link } from 'react-router-dom';
// 导入页面组件(需提前创建)
import Home from './pages/Home';
import About from './pages/About';
import User from './pages/User';
import NotFound from './pages/NotFound';
function App() {
return (
<div className="App">
<nav style={{ margin: '10px 0' }}>
<Link to="/" style={{ marginRight: '10px' }}>首页</Link>
<Link to="/about" style={{ marginRight: '10px' }}>关于我们</Link>
<Link to="/user/123">用户123</Link>
</nav>
{/* 路由匹配规则:Routes 是 v6 新增的容器(替代旧版 Switch) */}
<Routes>
{/* 基础路由:路径完全匹配时渲染对应组件 */}
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
{/* 动态路由:匹配 /user/任意值,通过 params 传参 */}
<Route path="/user/:id" element={<User />} />
{/* 404 路由:匹配所有未定义的路径(必须放最后) */}
<Route path="*" element={<NotFound />} />
</Routes>
</div>
);
}
export default App;
二、 深度解析路由两种模式底层原理
React Router 的本质是基于浏览器原生能力的封装,核心作用是根据 URL 路径匹配对应的组件并渲染,实现单页面应用(SPA)的无刷新页面切换。。
2. Hash 模式实现原理
Hash 模式依赖 URL 中 # 后的哈希值,核心逻辑如下:
-
URL 变化监听:基于
window.hashchange事件监听哈希值变化; -
设置 URL 值:通过
location.hash = '新路径'修改哈希值; -
获取当前 URL 值:通过
location.href或location.hash获取; -
URL 页面跳转:通过
location.assign('#/新路径')实现跳转; -
核心优势:
#后的内容不会发送到服务器,所有请求都指向域名/index.html,服务端无需额外配置。
3. History 模式实现原理
History 模式依赖 HTML5 新增的 History API,核心逻辑如下:
-
URL 变化监听:基于
window.popstate事件监听浏览器前进 / 后退导致的 URL 变化; -
新增 / 替换历史记录:
history.pushState(stateObj, title, url):新增一条历史记录(无刷新跳转);history.replaceState(stateObj, title, url):替换当前历史记录(不新增记录);
-
获取当前 URL 值:通过
window.location.pathname获取; -
页面前进 / 后退:通过
history.go(number)(前进 / 后退指定步数)、history.back()(后退一步)实现; -
获取自定义状态:通过
history.state获取pushState传入的自定义状态对象; -
核心注意:URL 无
#,但刷新页面时浏览器会向服务器发送对应路径的请求,需服务端配置兜底,否则会 404。
四、 注意:History 模式的服务器配置
当你使用 History 模式 部署到 Nginx 时,最常见的问题是:点击页面内的 Link 没问题,但一按刷新就 404。
原因:History 模式下,浏览器会向服务器请求 /home 这个物理路径。服务器上并没有这个文件,因此报错。
解决方案:在 Nginx 配置中增加 try_files 指令,让所有找不到的请求都重定向到 index.html,交给 React Router 去处理。
location / {
root /usr/share/nginx/html; # 前端打包文件的存放目录
index index.html index.htm; # 默认访问文件
try_files $uri $uri/ /index.html; # 核心配置:如果找不到资源,统统指向 index.html
}
📝 总结
-
React 路由需先安装
react-router-dom,顶层包裹BrowserRouter(History 模式)或HashRouter(Hash 模式); -
核心使用
<Routes>/<Route>定义路由规则,<Link>实现导航; -
Hash 模式无需服务端配置,History 模式需在 Nginx 中配置
try_files兜底,避免刷新 404; -
React Router 本质是监听 URL 变化(Hash 监听
hashchange,History 监听popstate),匹配并渲染对应组件。