如何在React中动态添加路由组件
// 高阶组件,封装过的 router.js
import asyncComponent from "../utils/asyncComponent"; // 这个后面会有讲解
import BasicLayout from "../layout/BasicLayout";
import NotFount from '../components/NotFount'
const CallBack = asyncComponent(() => import('../pages/javascript/CallBack'))
const Closure = asyncComponent(() => import('../pages/javascript/Closure'))
const router = [
{
path: '/',
redirect: '/tool/content'
},
{
path: '/tool',
component: BasicLayout,
routes: [
{
path: '/javascript',
name: 'JS高级',
component: NotFount,
routes: [
{
path: '/fn',
name: '函数借调',
component: CallBack
},
{
path: '/closure',
name: '闭包',
component: Closure
}
]
}
]
}
]
处理路由文件,作为react中的每个组件
import { Route, Redirect } from 'react-router-dom'
export function routeWithSub(router, fatherPath, list) {
router.forEach(item => {
// 拼接路由路径
let path = fatherPath + item.path
item.path && item.component && list.push(<Route exact key={ path } path={ path } render={ props => ( <item.component { ...props } routes={item.routes ? item.routes : []} content={list} /> ) } />)
if (item.routes) {
routeWithSub(item.routes, path, list)
}
})
}
// 此处传入的就是 routejs 路由
export function withRoute(router) {
let routerList = [] // 父组件路由
let list = [] // 所有的子组件的路由
router.forEach(item => {
let path = item.path
// 如果存在子路由交给递归继续处理
if (item.routes) {
routeWithSub(item.routes, path, list)
// 父组件直接push
routerList.push(
<Route key={ path } path={ path } render={ props => (
<item.component {...props} routes={ item.routes } content={ list } />
)} />
)
} else if (item.redirect) {
routerList.push( <Redirect exact={ true } key={ item.path } from={ item.path } to={ item.redirect } /> )
}
})
return routerList
}
直接在App.js 中引入这两个文件
import React from 'react'
import { HashRouter as Router, Switch } from 'react-router-dom'
import { withRoute } from './utils/route'
import router from './router/index'
export default class App extends React.Component {
render() {
const routerList = withRoute(router)
return (
<Router>
<Switch>
{ routerList }
</Switch>
</Router>
)
}
}
直接可以使用router.js 渲染路由菜单 如图
最后附上关于一个高阶函数,引入加载nprogress
- asyncComponent.js
import React from 'react'
import nprogress from 'nprogress'
import 'nprogress/nprogress.css'
/**
* 从加载时到加载结束用nprogress
* @param {*} importComponent 传入的组件
* @returns 高阶组件封装过的
*
*/
export default function asyncComponent(importComponent) {
class AsyncComponent extends React.Component {
constructor(props) {
super(props)
// 开始加载
nprogress.start()
this.state = {
component: null
}
}
async componentDidMount() {
// Es6 解构赋值 先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
const { default: component } = await importComponent()
// 加载完成
nprogress.done()
this.setState({
component: component
})
}
render() {
const C = this.state.component
return C ? <C { ...this.props }></C> : null
}
}
return AsyncComponent
}
如有问题,欢迎吐槽,共同学习,共同进步。