【REACT18.x】封装react-rouer实现多级路由嵌套,封装登录态权限拦截

发布于:2025-08-05 ⋅ 阅读:(14) ⋅ 点赞:(0)

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)

也是实现了一模一样的跳转。而且代码也更简洁了。


网站公告

今日签到

点亮在社区的每一天
去签到