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} = props
return <Component navigate={navigate} location={location} params={params} usp={usp} />
}
- 创建路由
const createRoutes = (routesConfig) => {
return <>
{routesConfig.map((item) => {
let {path} = item
return <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 = component
const 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} = props
console.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 } = props
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 withRouter(HomeHeader)
也是实现了一模一样的跳转。而且代码也更简洁了。