返回顶部
首页 > 资讯 > 精选 >react自动化构建路由的实现方法
  • 167
分享到

react自动化构建路由的实现方法

2023-06-14 19:06:59 167人浏览 安东尼
摘要

这篇文章主要介绍了React自动化构建路由的实现方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。序在使用react-router-dom在编写项目的时候有种感觉就是,使用起

这篇文章主要介绍了React自动化构建路由的实现方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。


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

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的结构目录吧

项目目录结构

react自动化构建路由的实现方法

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

react自动化构建路由的实现方法

这个组件我们把它创建在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数据并且声称这样的组件,每一步的作用我都已经在上面用注释标明了

4.使用CompileRouter

其实我们可以把封装的这个组件当成是vue-router中的视图组件<router-view/>就暂且先这么认为吧,接下来我们需要在页面上渲染1级路由了

在src/app.js

import React from 'react'import { HashRouter as Router, Link } from 'react-router-dom'//引入我们封装的CompileRouter罪案import CompileRouter from "./utils/compileRouter"//引入在1中定义的路由配置数据import routes from "./router"console.log(routes)class App extends React.Component {    render() {        return (            <Router>                <Link to="/friends">朋友</Link>                |                <Link to="/discover">发现</Link>                |                <Link to="/mine">我的</Link>                {}                <CompileRouter routes={routes} />            </Router>        )    }}export default App

写完后,那么页面上其实就可以完美的展示1级路由了

5.嵌套路由处理

上面我们已经对1级路由进行了渲染,可以跳转,但是二级路由怎么处理呢?其实也很简单,我们只需要找到二级路由的父路由,继续使用CompileRouter就可以了
我们从配置中可以看到,Discover这个路由是具有嵌套路由的,所以我们就以Discover路由为例子,首先我们看下结构图

react自动化构建路由的实现方法

图上的index.js就是Discover这个视图组件了,也是嵌套路由的父级路由,所以我们只需要在这个index.js中继续使用CompileRouter就可以了

import React from 'react'import { Link } from "react-router-dom"import CompileRouter from "../../utils/compileRouter"function Discover(props) {    let { routes } = props //这个数据是从ComileRouter组件编译的时候传递过来的children    // console.log(routes)    let links = routes.map(route => {        return (            <li key={route.path}>                <Link to={route.path}>{route.path}</Link>            </li>        )    })    return (        <fieldset>            <legend>发现</legend>            <h2>我发现,不能说多喝热水</h2>            <ul>                {links}            </ul>            {}            <CompileRouter routes={routes} />        </fieldset>    )}Discover.meta = {    title: "发现",    icon: ""}export default Discover

所以我们以后记住,只要是有嵌套路由我们要做两件事

  • 配置routes

  • 在嵌套路由的父级路由中再次使用CompileRouter,并且传入routes即可

6. require.context

上面我们实现了一个路由集中式的配置,但是我们会发现一个问题

react自动化构建路由的实现方法

引入了很多的组件,实际上,在项目中引入的更多,如果一个一个引入,对我们来说是灾难性的,所以我们可以使用webpack提供的一个很好用的api,require.context我们先说说它是怎么使用的吧
自动化导入require.context方法,使用这个方法可以减少繁琐的组件引入,而且可以深度的递归目录,做到import做不到的事情 下面我们来看一下这个方法是如何使用的

使用

你可以通过 require.context() 函数来创建自己的 context。
可以给这个函数传入4个参数:

  • 一个要搜索的目录,

  • 一个标记表示是否还要搜索其子目录,

  • 一个匹配文件的正则表达式

  • mode  模块加载模式,常用值为 sync、lazy、lazy-once、eager

    • sync 直接打包到当前文件,同步加载并执行

    • lazy 延迟加载会分离出单独的 chunk 文件

    • lazy-once 延迟加载会分离出单独的 chunk 文件,加载过下次再加载直接读取内存里的代码。

    • eager 不会分离出单独的 chunk 文件,但是会返回 promise,只有调用了 promise 才会执行代码,可以理解为先加载了代码,但是我们可以控制延迟执行这部分代码。

WEBpack 会在构建中解析代码中的 require.context() 。

语法如下:

require.context(  directory,  (useSubdirectories = true),  (regExp = /^\.\/.*$/),  (mode = 'sync'));

示例:

require.context('./test', false, /\.test\.js$/);//(创建出)一个 context,其中文件来自 test 目录,request 以 `.test.js` 结尾。require.context('../', true, /\.stories\.js$/);// (创建出)一个 context,其中所有文件都来自父文件夹及其所有子级文件夹,request 以 `.stories.js` 结尾。

api

函数有三个属性:resolve, keys, id。

resolve 是一个函数,它返回 request 被解析后得到的模块 id。

let p = require.context("...",true,"xxx")p.resolve("一个路径")

keys 也是一个函数,它返回一个数组,由所有可能被此 context module 处理的请求(译者注:参考下面第二段代码中的 key)组成。

require.context的返回值是一个函数,我们可以在函数中传入文件的路径,就可以得到模块化的组件了

let components = require.context('../pages', true, /\.js$/, 'sync')let paths = components.keys()//获得了所有引入文件的地址// console.log(paths)let routes = paths.map(path => {    let component = components(path).default    path = path.substr(1).replace(/\/\w+\.js$/,"")    return {        path,        component    }})console.log(routes)

总结

虽然上面有很多api和返回的值,我们只拿两个来做说明

keys方法,这个可以获取所有模块的路径,返回的是一个数组

let context = require.context("../pages", true, /\.js$/);let paths = context.keys()//获取了所有文件的路径

获取路径下所有的模块

let context = require.context("../pages", true, /\.js$/);let paths = context.keys()//获取了所有文件的路径let routes = paths.map(path => {    //批量获取引入的组件    let component = context(path).default;    console.log(component)    })

掌握这两个就可以了,下面我们来继续处理

7.扁平数据转换为树形结构的(convertTree算法)

这个算法的名字是我自己起的,首先我们要明白为甚么需要将数据转换成tree
我们的预期的routes数据应该是下面这样的

//目的是什么?//生成一个路由配置 const routes = [     {         path: "",         component:xxx          children:[                 {                     path:"xxx"                     component:xxx                 }            ]     } ]

但其实我们使用require.context处理之后的数据是这样的

react自动化构建路由的实现方法

可以看到这个数据是完全扁平化的,没有任何的嵌套,所以我们第一步就是要实现将这种扁平化的数据转换为符合我们预期的树形结构,下面我们一步一步来

7.1使用require.context将数据处理成扁平化

首先要处理成上图那样的结构,代码都有注释,难度也不高

//require.context()// 1. 一个要搜索的目录,// 2. 一个标记表示是否还要搜索其子目录, // 3. 一个匹配文件的正则表达式。let context = require.context("../pages", true, /\.js$/);let paths = context.keys()//获取了所有文件的路径let routes = paths.map(path => {    //批量获取引入的组件    let component = context(path).default;    //组件扩展属性方便渲染菜单    let meta = component['meta'] || {}    //console.log(path)    //这个正则的目的    //因为地址是./Discover/Djradio/index.js这种类型的并不能直接使用,所以要进行处理    //1.接去掉最前的"." 得到的结果是/Discover/Djradio/index.js    //2.处理了还是不能直接用 因为我们的预期/Discover/Djradio,所以通过正则将index.js干掉了    //3.有可能后面的路径不是文件夹 得到的结果是/Discover/abc.js,后缀名并不能用到路由配置的path属性中,所以.js后缀名又用正则替换掉    path = path.substr(1).replace(/(\/index\.js|\.js)$/, "")    // console.log(path)    return {        path,        component,        meta    }})

7.2 实现convertTree算法

上面处理好了数据后,我们封装一个方法,专门用于处理扁平化数据变成树形数据,算法时间复杂度为O(n^2)

function convertTree(routes) {    let treeArr = [];    //1.处理数据 将每条数据的id和parent处理好 (俗称 爸爸去哪儿了)    routes.forEach(route => {        let comparePaths = route.path.substr(1).split("/")        // console.log(comparePaths)        if (comparePaths.length === 1) {            //说明是根节点,根节点不需要添加parent_id            route.id = comparePaths.join("")        } else {            //说明具有父节点            //先处理自己的id            route.id = comparePaths.join("");            //comparePaths除去最后一项就是parent_id            comparePaths.pop()            route.parent_id = comparePaths.join("")        }    })    //2.所有的数据都已经找到了父节点的id,下面才是真正的找父节点了    routes.forEach(route => {        //判断当前的route有没有parent_id        if (route.parent_id) {            //有父节点            //id===parent_id的那个route就是当前route的父节点            let target = routes.find(v => v.id === route.parent_id);            //判断父节点有没有children这个属性            if (!target.children) {                target.children = []            }            target.children.push(route)        } else {            treeArr.push(route)        }    })    return treeArr}

通过上述处理之后就可以得到树形结构啦

react自动化构建路由的实现方法

接下来我们只需要把数据导出去,在app上引入传递给CompileRouter组件就可以了

7.3 以后要注意的

以后只需要在pages中创建文件即可自动实现路由的处理以及编译了,不过对于嵌套级别的路由咱们别忘了要在路由组件加上CompileRouter组件,总结为亮点

  • 创建路由页面

  • 嵌套路由的父级路由组件中加入

8.扩展静态属性

我们当前创建出来的效果是有了,但是如果我们用于渲染菜单的时候就会有问题,没有内容可以用于渲染菜单,所以我们可以给组件上扩展静态属性meta(也可以是别的),然后对我们的自动化编译代码做一些小小的改动就行了

组件

react自动化构建路由的实现方法

自动化处理逻辑完整代码

//require.context()// 1. 一个要搜索的目录,// 2. 一个标记表示是否还要搜索其子目录, // 3. 一个匹配文件的正则表达式。let context = require.context("../pages", true, /\.js$/);let paths = context.keys()//获取了所有文件的路径let routes = paths.map(path => {    //批量获取引入的组件    let component = context(path).default;    //组件扩展属性方便渲染菜单    let meta = component['meta'] || {}    //console.log(path)    //这个正则的目的    //因为地址是./Discover/Djradio/index.js这种类型的并不能直接使用,所以要进行处理    //1.接去掉最前的"." 得到的结果是/Discover/Djradio/index.js    //2.处理了还是不能直接用 因为我们的预期/Discover/Djradio,所以通过正则将index.js干掉了    //3.有可能后面的路径不是文件夹 得到的结果是/Discover/abc.js,后缀名并不能用到路由配置的path属性中,所以.js后缀名又用正则替换掉    path = path.substr(1).replace(/(\/index\.js|\.js)$/, "")    // console.log(path)    return {        path,        component,        meta    }})//这种数据是扁平化的数据,并不符合我们的路由规则//需要做算法 尽可能将时间复杂度降低o(n)最好//封装一个convertTree算法 时间复杂度o(n^2)// console.log(routes)//id//parent_idfunction convertTree(routes) {    let treeArr = [];    //1.处理数据 将每条数据的id和parent处理好 (俗称 爸爸去哪儿了)    routes.forEach(route => {        let comparePaths = route.path.substr(1).split("/")        // console.log(comparePaths)        if (comparePaths.length === 1) {            //说明是根节点,根节点不需要添加parent_id            route.id = comparePaths.join("")        } else {            //说明具有父节点            //先处理自己的id            route.id = comparePaths.join("");            //comparePaths除去最后一项就是parent_id            comparePaths.pop()            route.parent_id = comparePaths.join("")        }    })    //2.所有的数据都已经找到了父节点的id,下面才是真正的找父节点了    routes.forEach(route => {        //判断当前的route有没有parent_id        if (route.parent_id) {            //有父节点            //id===parent_id的那个route就是当前route的父节点            let target = routes.find(v => v.id === route.parent_id);            //判断父节点有没有children这个属性            if (!target.children) {                target.children = []            }            target.children.push(route)        } else {            treeArr.push(route)        }    })    return treeArr}export default convertTree(routes)//获取一个模块// console.log(p("./Discover/index.js").default)//目的是什么?//生成一个路由配置// const routes = [//     {//         path: "",//         component,//          children:[//                 {path component}//             ]//     }// ]

感谢你能够认真阅读完这篇文章,希望小编分享的“react自动化构建路由的实现方法”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网精选频道,更多相关知识等着你来学习!

--结束END--

本文标题: react自动化构建路由的实现方法

本文链接: https://lsjlt.com/news/274522.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • react自动化构建路由的实现方法
    这篇文章主要介绍了react自动化构建路由的实现方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。序在使用react-router-dom在编写项目的时候有种感觉就是,使用起...
    99+
    2023-06-14
  • react自动化构建路由的实现
    目录序1.路由集中式2.文件目录3.创建CompileRouter4.使用CompileRouter5.嵌套路由处理6. require.context使用api总结7.扁平数据转换...
    99+
    2024-04-02
  • Vue中怎么实现自动化路由
    Vue中怎么实现自动化路由,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。为什么要自动化路由路由自动化在于解决以下的问题:每次新...
    99+
    2024-04-02
  • React中配置子路由的实现方法
    这篇文章将为大家详细讲解有关React中配置子路由的实现方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1、组件First.js下有子组件:import Admin from&nbs...
    99+
    2023-06-15
  • vue3.0路由自动导入的方法实例
    一、前提 我们使用的是require.context方法导入,在vite创建的项目内使用会报错"require not found",所以必须用webpack创建项目。或者有大能可...
    99+
    2024-04-02
  • React中的路由嵌套和手动实现路由跳转的方式详解
    目录React的路由嵌套手动路由的跳转React的路由嵌套 接上一篇文章, 在上一篇文章中讲解了路由的基本介绍, 我再来介绍一下路由的其他用法 在开发中,路由之间是存在嵌套关系的。 ...
    99+
    2022-11-13
    react路由嵌套 react路由跳转 react手动路由跳转
  • react路由守卫的实现(路由拦截)
    react不同于vue,通过在路由里设置meta元字符实现路由拦截。在使用 Vue ,框架提供了路由守卫功能,用来在进入某个路有前进行一些校验工作,如果校验失败,就跳转到 404 或...
    99+
    2024-04-02
  • React配置子路由的实现
    1、组件First.js下有子组件: import Admin from './Admin' import FormCom from './FormCom' import One...
    99+
    2024-04-02
  • react嵌套路由实现TabBar的实现
     有两种页面,一种是有TabBar的页面,如下图; 一种是无TabBar的页面 有TabBar的页面使用嵌套路由来实现 嵌套路由:路由内部包含路由 使用步骤 1 在pag...
    99+
    2022-11-13
    react嵌套路由实现TabBar react TabBar
  • ASP.NET Core自动生成小写破折号路由的实现方法
    目录1、如何生成小写的路由可以这样设置2、生成带破折号并且小写的路由可以这样设置3、解决方案3.1对于Asp.NetCore2.2MVC:3.2  对于Asp.N...
    99+
    2024-04-02
  • 实现ASP.NET Core自动生成小写破折号路由的方法
    这篇文章主要讲解了“实现ASP.NET Core自动生成小写破折号路由的方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“实现ASP.NET Core自动生成小写破折号路由的方法”吧!默认情...
    99+
    2023-06-14
  • vue动态路由的实现方法有哪些
    本篇内容介绍了“vue动态路由的实现方法有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!vue动态路由的两种实现方法:1、简单的角色路由...
    99+
    2023-07-04
  • React路由动画切换实现过程详解
    目录1.下载2.配置3.引入css4.结合animate库1.下载 cnpm install react-transition-group --save 2.配置 在路由配置文件/s...
    99+
    2022-12-08
    React路由动画切换 React路由切换
  • Vue实现路由过渡动效的4种方法
    Vue 路由过渡是对 Vue 程序一种快速简便的增加个性化效果的的方法。 可以让你在程序的不同页面之间增加平滑的动画和过渡。如果使用得当,可以使你的程序显得更加专业,从而增强用户体验...
    99+
    2024-04-02
  • vue动态路由有哪两种实现方法
    本教程操作环境:windows7系统、vue3版,DELL G3电脑。动态路由不同于常见的静态路由,可以根据不同的「因素」而改变站点路由列表。动态路由设置一般有两种:(1)、简单的角色路由设置:比如只涉及到管理员和普通用户的权限。通常直接在...
    99+
    2023-05-14
    动态路由 Vue
  • Django3.2自动发现所有路由怎么实现
    这篇文章主要讲解了“Django3.2自动发现所有路由怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Django3.2自动发现所有路由怎么实现”吧!1.需求发现项目本地所有带别名的U...
    99+
    2023-06-21
  • 如何实现多个vue子路由文件自动化合并
    小编给大家分享一下如何实现多个vue子路由文件自动化合并,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1. 目录结构目录结构,如...
    99+
    2024-04-02
  • 使用Spring由构造方法自动装配
    Spring由构造方法自动装配 在Spring中,可以使用“通过构造自动装配”,实际上是按构造函数的参数 类型自动装配。 这意味着,如果一个bean的数据类型与其他bean的构造器参...
    99+
    2024-04-02
  • SpringBoot根据目录结构自动生成路由前缀的实现代码
    目录前言具体实现配置文件指定基础包自动补全路由前缀处理类自动补全路由前缀配置类测试类测试前言 本文介绍如何根据目录结构给RequestMapping添加路由前缀(覆盖RequestM...
    99+
    2024-04-02
  • react中路由跳转及传参的实现
    目录1.useNavigate2.useLocation3.示例1.useNavigate useNavigate 是 React Router v6 中新增的一个 hoo...
    99+
    2023-05-19
    react 路由跳转 react 路由传参
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作