react自动化构建路由

本文介绍了如何在React项目中实现自动化构建路由,包括集中式路由配置、文件目录结构、CompileRouter组件的创建与使用,以及如何处理嵌套路由。通过require.context API减少手动引入组件,并展示了将扁平数据转换为树形结构的convertTree算法。最终,文章还讨论了扩展静态属性以解决渲染菜单的问题。
摘要由CSDN通过智能技术生成

react自动化构建路由

在使用react-router-dom在编写项目的时候有种感觉就是,使用起来非常的方便,但是若是维护起来,那便是比较麻烦了,因为各大路由分散在各个组件中. 所以我们就会想到,使用react-router-dom中提供的config模式来编写我们的路由,这样写的好处就是我们可以将逻辑集中在一处,配置路由比较方便

项目地址

https://gitee.com/d718781500/autoRouter

1.路由集中式

我们先将下列数据定义在/src/router/index.js

在react的路由官方文档中就提供了配置集中式路由的案例,大致是这样的仿照vue的路由,生成一个配置文件,预期是这样的

//需要一个路由的配置,它是一个数组
import Discover from "../pages/Discover"
import Djradio from "../pages/Discover/Djradio"
import Playlist from "../pages/Discover/Playlist"
import Toplist from "../pages/Discover/Toplist"
import Friends from "../pages/Friends"
import Mine from "../pages/Mine"
import Page404 from "../pages/Page404"
const routes = [
    {
        path: "/friends",
        component: Friends
    },
    {
        path: "/mine",
        component: Mine
    },

    {
        path: "/discover",
        component: Discover,
        children: [
            {
                path: "/discover/djradio",
                component: Djradio
            },
            {
                path: "/discover/playlist",
                component: Playlist

            },
            {
                path: "/discover/toplist",
                component: Toplist
            }
        ]
    },
    {//Page404这个配置一定要在所有路由配置之后
        path: "*",
        component: Page404
    }
]

export default routes

我们可以通过上述配置,来生成一个路由.当然上述的配置也只是做了简单的处理,还有redirect exact等属性没有写,我们还是从一个简单的开始吧

2.文件目录

上述的配置中使用了类似于vue的集中式路由配置模式,那么下面就展示下我当前这个demo的结构目录吧

项目目录结构

img

src/pages目录结构

├─Discover
│  │  abc.js
│  │  index.js
│  │
│  ├─Djradio
│  │  │  index.js
│  │  │  lf.js
│  │  │
│  │  └─gv
│  │          index.js
│  │
│  ├─Playlist
│  │      index.js
│  │
│  └─Toplist
│          index.js
│
├─Entertaiment
│      index.js
│
├─Friends
│      index.js
│      xb.js
│
├─Mine
│      index.js
│
└─Page404
        index.js

有了这些结构之后,那么在1中提到的引入文件结合起来看就不懵逼啦,接下来我们可以封装一个组件,给他取个名字叫做CompileRouter这个组件专门用于编译路由

3.创建CompileRouter

img

这个组件我们把它创建在src/utils中,作用就是通过传入的路由配置,然后计算出这个组件,那么问题来了,为什么要创建这个组件呢?

让我们回顾一下react路由的编写方式吧,react路由需要一个基础组件HashRouter或者BrowserRouter这两个相当于一个基石组件

然后还需要一个路由配方这个组件可以接受一个path映射一个component

我们来写段伪代码来说明一下

//引入路由基本组件(要在项目中安装 npm i react-router-dom)
import {HashRouter as Router,Route} from "react-router-dom"
class Demo extends React.Component {
    render(){
        //基石路由
        <Router>
            //路由配方组件 通过path匹配component
            <Route path="/" component={Home}/>
             <Route path="/mine" component={Mine}/>
        </Router>
    }
}

这是基本用法,所以我们CompileRouter这个组件的工作就是,生成如上代码中的Route一样,生成Route然后展示在组件上

在了解到Compile的基本作用之后,下面我们就开始编码吧

我个CompileRouter设计是接受一个数据,这个数据必须是符合路由配置的一个数组,就像1里代码中所示的数组一样,接受的属性为routes

//这个文件通过routes配置来编译出路由
import React from 'react'
import { Switch, Route } from "react-router-dom";
export default class CompileRouter extends React.Component {
    constructor() {
        super()
        this.state = {
            c: []
        }
    }
    renderRoute() {
        let { routes } = this.props;//获取routes路由配置
        //1.通过routes生成Route组件
        //确保routes是一个数组
        // console.log(routes)
        //render 不会重复让组件的componentDidMount和componentWillUnmount重复调用
        if (Array.isArray(routes) && routes.length > 0) {
            //确保传入的routes是个数组
           // 循环迭代传入的routes
            let finalRoutes = routes.map(route => {
                //每个route是这个样子的 {path:"xxx",component:"xxx"}
                //如果route有子节点 {path:"xxx",component:"xxx",children:[{path:"xxx"}]}
                return <Route path={route.path} key={route.path} render={
                       // 这么写的作用就是,如果路由还有嵌套路由,那么我们可以把route中的children中的配置数据传递给这个组件,让组件再次调用CompileRouter的时候就能编译出嵌套路由了
                    () => <route.component routes={route.children} />
                } />
            })

            this.setState({
                c: finalRoutes
            })
        } else {
            throw new Error('routes必须是一个数组,并且长度要大于0')
        }
    }
    componentDidMount() {
        //确保首次调用renderRoute计算出Route组件
        this.renderRoute()
    }
    render() {
        let { c } = this.state;
        return (
            <Switch>
                {c}
            </Switch>
        )
    }
}

上述代码就是用于去处理routes数据并且声称这样的组件,每一步的作用我都已经在上面用注释标明了

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值