希望达到跟 vue
一样,在 js
配置中则完成路由重定向的等基础操作,不太习惯使用 Routes、Route
等互相包裹的方式。
所有基于 react-router-dom@6.15.0
封装了一个路由组件,并附带展示个路由守卫组件。
路由组件 - ExRouter.tsx
:
扩展路由配置,支持重定向,以及方便扩展其他属性。
// 基于 react-router-dom@6.15.0 封装
import { useRoutes, Navigate, RouteObject, IndexRouteObject, NonIndexRouteObject } from 'react-router-dom'
import { useLocation, Location } from 'react-router'
/**
* @description: 扩展属性
*/
interface ExRouteObjectProps {
/**
* @description: 重定向路由地址
*/
redirect?: string,
/**
* @description: 子列表
*/
children?: ExRouteObject[]
}
/**
* @description: 扩展 IndexRouteObject
*/
export interface ExIndexRouteObject extends Omit<IndexRouteObject, 'children'>, ExRouteObjectProps {
}
/**
* @description: 扩展 NonIndexRouteObject
*/
export interface ExNonIndexRouteObject extends Omit<NonIndexRouteObject, 'children'>, ExRouteObjectProps {
}
/**
* @description: 路由对象类型
*/
export type ExRouteObject = ExIndexRouteObject | ExNonIndexRouteObject
/**
* @description: 找到路由对象类型
*/
type ExRouteObjectFind = ExRouteObject | undefined
/**
* @description: 组件参数
*/
export interface ExRouterProps {
/**
* @description: 路由列表
*/
routes: ExRouteObject[]
}
const Component = (props: ExRouterProps) => {
// 当前导航对象
const location = useLocation()
// 找到路由对象
const findRoute = (routes: ExRouteObject[], location: Location): ExRouteObjectFind => {
// 当前层级检查一轮
let route: any = routes.find((item: any) => item.path === location.pathname)
// 没有则搜索当前层级同级子页面
if (!route) {
// 排查,找到停止
routes.some((item: any) => {
// 取出子列表
const children: ExRouteObject[] = item?.children || []
// 子列表有值
if (children.length) {
// 进行排查
route = findRoute(children, location)
}
// 有值则暂停
return !!route
})
}
// 返回
return route
}
// 找到当前路由
const route: ExRouteObjectFind = findRoute(props.routes, location)
// 返回渲染
return (
<>
{/* 加载所有路由 */}
{ useRoutes(props.routes as RouteObject[]) }
{/* 检查当前路由是否需要重定向 */}
{ route?.redirect && <Navigate to={route.redirect} replace /> }
</>
)
}
export default Component
路由拦截(路由守卫)组件:
// import { Navigate, useLocation, useSearchParams } from 'react-router-dom'
const Component = (props: any) => {
// // 接收路由参数
// const [searchParams] = useSearchParams()
// // 当前导航对象
// const location = useLocation()
// // token (检查本地或路由参数)
// const token = 'xxxx'
// // console.log(location, searchParams.get('token'))
// // 路由权限校验
// if (location.pathname.includes('/login') && token) {
// // 跳转登录页 && token有值
// return
// } else if (!location.pathname.includes('/login') && !token) {
// // 不是跳转登录页 && token无值
// return
// }
// 验证通过
return props.children
}
export default Component
上面两个组件在路由中的使用:
import React from 'react'
import { ExRouteObject } from './ExRouter'
import { Navigate } from 'react-router-dom'
import BeforeEach from './BeforeEach'
import ExRouter from './ExRouter'
// 懒加载
const lazyload = (path: string) => {
// 加载组件
let Component=React.lazy(()=>{return import (`@/${path}`)})
// 返回渲染
return (
<React.Suspense fallback={<>请等待·····</>}>
<Component />
</React.Suspense>
)
}
// 菜单路由
export const menuRoutes: ExRouteObject[] = [
{
path: '/layout',
redirect: '/layout/home',
element: lazyload('layouts/BaseLayout'),
children: [
{
path: '/layout/home',
redirect: '/layout/home/home1',
// element: lazyload('views/home'),
children: [
{
path: '/layout/home/home1',
element: lazyload('views/home')
}
]
}
]
}
]
// 路由列表
const routes: Record<string, any>[] = [
...menuRoutes,
{
path: '/home',
element: lazyload('views/home'),
},
{
path: '/user',
element: lazyload('views/user'),
},
{
path: "/404",
element: (<>页面地址不存在</>),
},
{ path: "/", element: <Navigate to="/home" /> },
{ path: "*", element: <Navigate to="/404" /> },
]
// 加载配置式路由
function Router () {
return (
<BeforeEach>
<ExRouter routes={routes}></ExRouter>
</BeforeEach>
)
}
// 导出
export default Router