1. React Router v5 基础入门
作为React生态中最核心的路由解决方案,React Router v5至今仍是许多存量项目的标配。我在多个企业级项目中深度使用过这个版本,发现很多新手在基础配置环节就会遇到各种"坑"。让我们从最基础的安装开始,一步步拆解这个经典路由库的核心用法。
首先通过npm安装(确保已初始化项目):
bash复制npm install react-router-dom@5.3.0
注意:v5与v6有重大API变更,如果看到useNavigate等新API的教程,那一定是v6的写法。企业老项目大多仍在使用v5,这也是本文聚焦v5的原因。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 路由模式选择与初始化
2.1 BrowserRouter 的配置要点
BrowserRouter是基于HTML5 History API的路由模式,需要后端配合支持。在项目入口文件(通常是index.js)这样引入:
jsx复制import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
关键配置参数:
- basename:设置基础路径(如部署在子目录时)
- forceRefresh:是否强制刷新页面(默认为false)
- getUserConfirmation:导航确认回调函数
实际踩坑:在Nginx部署时,记得配置try_files避免刷新404:
code复制location / {
try_files $uri /index.html;
}
2.2 HashRouter 的替代方案
如果后端无法配置History模式,可以用HashRouter(URL带#号)。但要注意:
- 不利于SEO
- 锚点功能会冲突
- 服务端无法获取#后的路径
jsx复制import { HashRouter } from 'react-router-dom';
3. 路由定义与匹配规则
3.1 Route 组件的核心用法
Route是定义路由匹配规则的核心组件,有几种渲染方式:
jsx复制// 方式1:component(最常用)
<Route path="/users" component={Users} />
// 方式2:render(需要传参时用)
<Route path="/users" render={(props) => <Users {...props} extra={data} />} />
// 方式3:children(无论是否匹配都渲染)
<Route path="/users" children={<Users />} />
路径匹配的三种模式:
- exact:精确匹配(path必须完全相等)
- strict:严格匹配(区分尾部斜杠)
- sensitive:区分大小写
3.2 Switch 的匹配策略
Switch组件会按顺序匹配第一个符合条件的Route,常见问题:
jsx复制<Switch>
<Route path="/users/new" component={NewUser} />
<Route path="/users/:id" component={UserDetail} />
<Route path="/users" component={Users} />
</Switch>
关键经验:路径要从具体到通用排列,否则"/users/new"会先匹配"/users/:id"
4. 导航与链接跳转
4.1 Link 与 NavLink 的对比
基础跳转用Link:
jsx复制<Link to="/about">关于我们</Link>
需要高亮当前菜单时用NavLink:
jsx复制<NavLink
to="/about"
activeClassName="active"
activeStyle={{ fontWeight: 'bold' }}
exact
>
关于我们
</NavLink>
4.2 编程式导航的三种方式
在类组件中:
jsx复制// 方式1:通过props.history
this.props.history.push('/users');
// 方式2:withRouter高阶组件
import { withRouter } from 'react-router-dom';
export default withRouter(MyComponent);
// 方式3:Redirect组件
<Redirect to="/login" />
在函数组件中(v5方案):
jsx复制import { useHistory } from 'react-router-dom';
function MyComponent() {
const history = useHistory();
history.push('/users');
}
5. 动态路由与参数获取
5.1 路径参数的使用
定义带参数的路由:
jsx复制<Route path="/users/:id" component={UserDetail} />
在组件中获取参数:
jsx复制// 类组件
this.props.match.params.id
// 函数组件
import { useParams } from 'react-router-dom';
const { id } = useParams();
5.2 查询参数的处理
传统URL查询字符串(?name=value)需要手动解析:
jsx复制import qs from 'querystring';
// 获取search字符串
const search = this.props.location.search;
const params = qs.parse(search.slice(1));
更现代的URLSearchParams API:
jsx复制const params = new URLSearchParams(this.props.location.search);
params.get('name');
6. 路由守卫与权限控制
6.1 基础路由守卫实现
封装PrivateRoute组件:
jsx复制function PrivateRoute({ component: Component, ...rest }) {
const isAuth = checkAuth(); // 你的认证逻辑
return (
<Route
{...rest}
render={props =>
isAuth ? (
<Component {...props} />
) : (
<Redirect to="/login" />
)
}
/>
);
}
6.2 基于路由的权限体系
结合角色权限的路由配置:
jsx复制const routes = [
{
path: '/admin',
component: Admin,
roles: ['admin'],
children: [...]
},
{
path: '/dashboard',
component: Dashboard,
roles: ['admin', 'user']
}
];
function checkPermission(route, userRole) {
return !route.roles || route.roles.includes(userRole);
}
7. 嵌套路由的实现方案
7.1 静态嵌套路由配置
父路由组件中定义子路由:
jsx复制function Parent() {
return (
<div>
<h2>Parent Layout</h2>
<Route path="/parent/child" component={Child} />
</div>
);
}
7.2 动态渲染子路由
通过props.match.path构建嵌套路径:
jsx复制function Parent(props) {
return (
<div>
<h2>Parent Layout</h2>
<Route path={`${props.match.path}/child`} component={Child} />
</div>
);
}
8. 常见问题排查指南
8.1 路由不匹配的调试技巧
- 检查BrowserRouter是否包裹在最外层
- 确认路径拼写(特别是动态参数)
- 检查Switch中路由的顺序
- 查看exact/strict/sensitive的配置
- 用withRouter包裹组件确认是否能获取路由props
8.2 性能优化建议
- 对动态导入的组件使用React.lazy:
jsx复制const Users = React.lazy(() => import('./Users'));
<Suspense fallback={<Spinner />}>
<Route path="/users" component={Users} />
</Suspense>
- 避免在render中内联函数:
jsx复制// 不推荐
<Route path="/users" render={() => <Users extra={data} />} />
// 推荐
const renderUsers = useCallback(() => <Users extra={data} />, [data]);
<Route path="/users" render={renderUsers} />
9. 项目结构最佳实践
9.1 集中式路由配置
创建routes.js统一管理:
jsx复制const routes = [
{
path: '/',
exact: true,
component: Home
},
{
path: '/users',
component: Users,
routes: [
{
path: '/users/:id',
component: UserDetail
}
]
}
];
function RouteWithSubRoutes(route) {
return (
<Route
path={route.path}
render={props => (
<route.component {...props} routes={route.routes} />
)}
/>
);
}
9.2 按功能模块拆分
典型项目结构:
code复制src/
features/
users/
Users.js
UserDetail.js
routes.js
products/
...
App.js
routes.js
在大型项目中,这种结构能更好地配合代码分割和懒加载。
