【REACT18.x】封装react-rouer实现多级路由嵌套,封装登录态权限拦截
react-router6有两种实现路由的方式,这里主要是记录下使用 Routes
实现的过程,不是用配置式。
同时还加入路由的全局懒加载,也可以根据自己的需要进行更精细的配置
实现效果
实现代码
- 在渲染组件之间可以做一些路由的拦截,登录态,权限拦截,传递路由信息等
- @param {*} item
- @returns
import routesConfig from './routes'
import { Suspense } from 'react'
import {Routes,Route,useNavigate,useLocation,useParams,useSearchParams} from 'react-router-dom'const Element = (props) => { /*** 获取路由信息,只要是router匹配的组件,都可以基于props获取到理由信息*/const navigate = useNavigate(),location = useLocation(),params = useParams(),[usp] = useSearchParams()/*** 把组件名改成大写*/const {component:Component} = propsreturn <Component navigate={navigate} location={location} params={params} usp={usp} />
}
- 创建路由
const createRoutes = (routesConfig) => {return <>{routesConfig.map((item) => {let {path} = itemreturn <Route path={path} element={<Element {...item} />} key={path}>{Array.isArray(item.children) && createRoutes(item.children)}</Route>})}</>
}
创建路由容器
export default function RoutesView(){return <Suspense fallback={<div>正在加载中...</div>}><Routes>{createRoutes(routesConfig)}</Routes></Suspense>
}
- 模拟被dom5删除的withRouter
- @param {*} Component 真实渲染的组件
- @returns
export const withRouter = component => props => {const Component = componentconst navigate = useNavigate(),location = useLocation(),params = useParams(),[usp] = useSearchParams()return <Component {...props} navigate={navigate} location={location} params={params} usp={usp} />
}
- 路由配置
import { Navigate } from 'react-router-dom';
import A from '../views/A'
// import B from '../views/B'
import C from '../views/C'
import { lazy } from 'react';// import A from './views/A'
// import B from './views/B'
// import C from './views/C'
// import A1 from './views/a/A1'
// import A2 from './views/a/A2'
// import A3 from './views/a/A3'const subRoutes = [{path:'/a',component : () => <Navigate to="/a/a1" />},{path:'/a/a1',name:'a-a1',component: lazy(() => import('../views/a/A1')),},{path:'/a/a2',name:'a-a2',component: lazy(() => import('../views/a/A2')),},{path:'/a/a3',name:'a-a3',component: lazy(() => import('../views/a/A3')),}
]const routes = [{path:'/',component: () => <Navigate to="/a" />},{path:'/a',component: A,name:'a',meta:{},children: subRoutes},{path:'/b',component: lazy(() => import('../views/B')),name:'b',meta:{},children: []},{path:'/c/:id?/:name?',component: C,name:'c',meta:{},children: []},{path:'*',component: () => <div>404</div>}
];
export default routes;
使用方法
- App.jsx
import React from 'react'
import { HashRouter, Routes,Route, Navigate } from 'react-router-dom'
import HomeHeader from './components/HomeHeader'
import routesView from './router'export default function App() {return (<HashRouter><HomeHeader /><div className="content">{routesView()}</div></HashRouter>)
}
思维扩展
在封装之前,我们要获取路由相关的信息,必须这样显示的导入相关hooks
封装之后,就不用了
- 页面B跳转到C,
navigate
可以直接从props
里面获取
import React from 'react'
// import qs from 'qs'
export default function B(props) {const {navigate} = props// 隐式传参const handleClick = () => {navigate('/c',{replace: true,state: {id: 200,name: 'gaofeng'}})}return (<div><button onClick={handleClick}>提交</button></div>)
}
- 页面C接受数据,
location
可以直接从props
里面获取
import React from 'react'
export default function C(props) {const {location} = propsconsole.log(location)return (<div>C</div>)
}
可以看到,C页面正常打印了B页面传递的数据
- 在App.jsx页面,是没有被Route包围的,所以在里面是无法从
props
中获取路由数据的
import React from 'react'
import { NavLink, useNavigate } from 'react-router-dom'
import { NavBox } from './styled'
function HomeHeader() {const navigate = useNavigate()const handleToPageB = () => {navigate('/b')}return (<><NavBox><NavLink to='/a'>A</NavLink><NavLink to='/b'>B</NavLink><NavLink to='/c'>C</NavLink></NavBox><button onClick={handleToPageB}>跳转到b页面</button></>)
}export default HomeHeader
使用withRouter高阶组件HOC
import React from 'react'
import { NavLink, useNavigate } from 'react-router-dom'
import { NavBox } from './styled'
import { withRouter } from '../router'
function HomeHeader(props) {// const navigate = useNavigate()const { navigate } = propsconst handleToPageB = () => {navigate('/b')}return (<><NavBox><NavLink to='/a'>A</NavLink><NavLink to='/b'>B</NavLink><NavLink to='/c'>C</NavLink></NavBox><button onClick={handleToPageB}>跳转到b页面</button></>)
}export default withRouter(HomeHeader)
也是实现了一模一样的跳转。而且代码也更简洁了。