admin管理员组文章数量:1634399
实现功能:
+ 全局路由统一管理,支持配置路由重定向、路由懒加载、自定义meta字段等。
+ 全局路由拦截,支持读取路由meta配置,支持拦截跳转其他路由等。
依赖版本:
+ `react@17.0.2`
+ `react-router-dom@5.3.0` // react-router v5
一、react路由
react-router-dom v5版本里,路由不再是js,而是一个个组件,即<Route />
。
通过path路径区分不同的路由来渲染。配合<Switch />
组件只渲染内部第一个匹配到的<Route />
这个特性,来实现不同的路由地址显示对应不同的页面。
基础结构大概长这样:
<Switch>
<Route path="/index" />
<Route path="/test" />
<Route path="/demo" />
</Switch>
二、路由统一管理
要实现路由的统一管理,类似vue-router那样配置一个js数组来管理路由,就要考虑写一个方法来根据路由配置数组来自动生成对应的jsx dom结构。
react-router-config
插件来之前能实现类似的效果,但插件已经很久没更新了,而且插件不支持路由懒加载,所以考虑手写实现。
1、路由配置文件
项目src/router/index.js
里填写路由配置:
import { lazy } from 'react'
export const routes = [
{
path: '/',
redirect: '/index', // 路由重定向字段
},
{
path: '/index',
component: lazy(() => import(/* webpackChunkName: "index" */ '@/views/index/index')),
meta: { // meta字段用来自定义路由配置
title: '首页',
},
},
{
path: '/login',
component: lazy(() => import(/* webpackChunkName: "login" */ '@/views/login/index')),
meta: {
title: '登录',
},
},
{
path: '*',
component: lazy(() => import(/* webpackChunkName: "404" */ '@/views/test/page404')),
meta: {
title: '404',
},
},
]
2、封装路由组件
项目src/components/GlobalRouter/index.jsx
里封装组件引入路由配置:
import { BrowserRouter, Switch } from 'react-router-dom'
import { Suspense } from 'react'
import RouterList from './routerList'
function GlobalRouter ({ routes }) {
return (
<BrowserRouter>
<Suspense fallback={<div>{/* loading */}</div>}>
<Switch>
<RouterList routes={routes} />
</Switch>
</Suspense>
</BrowserRouter>
)
}
export default GlobalRouter
项目src/components/GlobalRouter/routerList.jsx
里封装组件渲染路由列表:
import { Route, Redirect } from 'react-router-dom'
function routerList ({ routes, location }) {
const { pathname } = location
const route404 = routes.find(v => v.path === '*') || {}
const currentRoute = routes.find(v => v.path === pathname) || route404
return currentRoute.redirect
? (<Redirect to={currentRoute.redirect} />)
: (<Route exact {...currentRoute} />)
}
export default routerList
- 这里之所以又封装了一个
routerList.jsx
组件是利用了这个组件在<Switch>
包裹下能够通过props获取当前访问的路由location对象,后续就能依此做处理。 - 路由全部为精确匹配。
3、引入路由组件
项目入口文件src/index.js
(或根组件App.js)里配置引入封装好的组件:
import { StrictMode } from 'react'
import ReactDOM from 'react-dom'
import GlobalRouter from '@/components/GlobalRouter'
import { routes } from '@/router'
ReactDOM.render(
<StrictMode>
<GlobalRouter routes={routes} />
</StrictMode>,
document.getElementById('root')
)
这样就实现了基本的路由统一管理配置。
PS:
- 我这里是使用的路由history模式,如果是路由hash模式就把BrowserRouter替换成HashRouter。
- 如果项目是部署在服务器域名的子目录下,就给BrowserRouter添加basename属性,值为子目录路径,例如/h5。
三、全局路由拦截
实现路由全局拦截,来自定义一些判断处理,类似vue里的beforeEach钩子函数,这里就在上述封装好的文件里作修改。
1、路由拦截函数
项目src/router/index.js
里添加内容:
/**
* @description: 全局路由拦截
* @param {object} route 当前路由配置对象
* @return {string} 需要重定向到其他页时返回该页的path路径
*/
export function onRouterBefore (route) {
const meta = route.meta || {}
// 示例:动态修改页面title
if (meta.title !== undefined) {
document.title = meta.title
}
// 示例:未登录时跳转登录页
if (!isLogin) {
return '/login'
}
}
- 这里定的规则就是如果需要拦截跳转其他页,onRouterBefore就return一个返回值,值为要跳转的页面path路径,不需要跳转就不用return。
2、处理拦截函数
项目src/components/GlobalRouter/routerList.jsx
里修改内容:
function routerList ({ routes, location, onRouterBefore }) {
const { pathname } = location
const route404 = routes.find(v => v.path === '*') || {}
const currentRoute = routes.find(v => v.path === pathname) || route404
const resultPath = onRouterBefore && onRouterBefore(currentRoute)
if (resultPath && resultPath !== pathname) {
return <Redirect to={resultPath} />
} else {
return currentRoute.redirect
? (<Redirect to={currentRoute.redirect} />)
: (<Route exact {...currentRoute} />)
}
}
- 拦截跳转其他页面时都是采用的重定向跳转方式。
项目src/components/GlobalRouter/index.jsx
里接收onRouterBefore:
function GlobalRouter ({ routes, onRouterBefore }) {
return (
<BrowserRouter basename={process.env.PUBLIC_URL}>
<Suspense fallback={<div>{/* loading */}</div>}>
<Switch>
<RouterList routes={routes} onRouterBefore={onRouterBefore} />
</Switch>
</Suspense>
</BrowserRouter>
)
}
项目入口文件src/index.js
里传入onRouterBefore:
import { routes, onRouterBefore } from '@/router'
ReactDOM.render(
<StrictMode>
<GlobalRouter routes={routes} onRouterBefore={onRouterBefore} />
</StrictMode>,
document.getElementById('root')
)
这样全局路由拦截方案就大概完成了。
四、思考
1、插件化处理
- 配置文件都在
src/router
文件夹里; - 实现逻辑都在
src/components/GlobalRouter
组件文件夹里; - 配置文件与实现逻辑的解耦,方便用于多项目共享。
2、待优化点
- 暂未支持嵌套路由。
目前项目中已不再使用此方案,推荐另一更完整的解决方案:react-router v6 路由统一管理及路由拦截方案
参考链接:https://www.freesion/article/2728789511/
版权声明:本文标题:react-router 5 管理路由 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dongtai/1729176530a1188789.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论