「✍ React 」react-router-config集中管理路由

2,076 阅读1分钟

使用

router/config

路由配置

import Home from '../Home'
import Child from '../components/child'

export default [
  {
    path: '/home',
    component: Home,
    extra: true,
    childrens: [
      {
        path: '/home/child',
        component: Child
      }
    ]
  },
  {
    //...
  },
]

router/index

读取配置,利用renderRoutes渲染

import React from 'react'
import { HashRouter } from 'react-router-dom'
import { renderRoutes } from 'react-router-config'
import config from './config'

const Router = (
  <HashRouter>
    {
      renderRoutes(config)
    }
  </HashRouter>
)

export default Router

app.tsx

import React from 'react'
// 引入路由
import routes from './router/index'

import './icons'

import './App.less'

const App: React.FC = () => (
  <>
    { routes }
  </>
)

export default App

Home组件

import React from 'react'

const Home: React.FC<RouteConfigComponentProps<any>> = ({ route }) => {
 return (
  <div>
    <h1>this is home</h1>
    // 渲染子组件
    {renderRoutes(route.children, { content: "this is content for child" }) }
    
    // 原来的写法:
    <Route path="/home/child" component={ () => <Child content="this is child" /> } />
  </div>
 )
}

Child组件

import React from 'react'

const Child = ({ content }) => <h1>{ content }</h1>

export default Child

原理

renderRoutes源码

function renderRoutes(routes, extraProps, switchProps) {
  if (extraProps === void 0) {
    extraProps = {};
  }

  if (switchProps === void 0) {
    switchProps = {};
  }

  return routes ? React.createElement(Switch, switchProps, routes.map(function (route, i) {
    return React.createElement(Route, {
      key: route.key || i,
      path: route.path,
      exact: route.exact,
      strict: route.strict,
      render: function render(props) {
        return route.render ? route.render(_extends({}, props, {}, extraProps, {
          route: route
        })) : React.createElement(route.component, _extends({}, props, extraProps, {
          route: route
        }));
      }
    });
  })) : null;
}

其实就是遍历配置文件,创建<Route>组件

更多

添加根/父组件

有时候我们需要根据路由配置和当前路由来做一些逻辑,比如设置当前页面的title,我们可以这样 config

export default [
  {
    component: LayoutRoot,
    path: '/home',
    component: Home,
    extra: true,
    routes: [
      {
        path: '/home/child',
        component: Child
      }
    ]
  }
]

LayoutRoot

const LayoutRoot: React.FC<RouteConfigComponentProps> = (props) => {
  const { route, location } = props
  
  // 做逻辑
  setTitle(route, location)
  
  return (
    <>
      { route?.routes && renderRoutes(route.routes) }
    </>
  )
}

自定义配置

在配置文件中,除了基础配置,还可以延伸出一些用于业务的自定义配置

import Home from '../Home'
import Child from '../components/child'

export default [
  {
    path: '/home',
    component: Home,
    extra: true,
    auth: "HOME.INDEX", // 权限
    hidden: false,      // 是否在菜单栏隐藏
    routes: [
      {
        path: '/home/child',
        component: Child
      }
    ]
  }
]

上面的配置加入了权限和控制菜单栏中是否隐藏tab的配置,使用时自行发挥

app.tsx

import React from 'react'
// 引入路由
import routes from './router/index'

import './icons'

import './App.less'

const App: React.FC = () => (
  <>
    <SideBar routes = {routes} />  // 在SideBar组件中自行判断权限和hidden字段进行隐藏/展示的控制
    { routes }
  </>
)

export default App