React(react-router-dom) 根据路径自动配置路由,简单处理

React(react-router-dom) 根据路径自动配置路由,简单处理

# 创建 create-react-app
npx create-react-app my-app
cd my-app
npm start

在 src 目录下创建页面文件夹,如 pages

# 安装 react-router-dom
yarn add react-router-dom@5.3.0
// app.js

import './App.css';
import { BrowserRouter as Router, Route, Redirect, Link } from 'react-router-dom'

// 使用 webpack 的 require.context 方法,导入检索需要配置的文件
// './pages/':目标文件夹
// true:是否检索子文件夹
// /\.(tsx|jsx|js)$/:文件名匹配正则
const routers = require.context('./pages/', true, /\.(tsx|jsx|js)$/)
// context module 会导出一个(require)函数

// 路径处理,如 ./home/index[id].tsx 会被处理为 /home/:id
// [] 表示路径参数
function pathHandle(key) {
  let path = key
    .replace(/^\./, '')
    .replace(/\.(tsx|jsx|js)$/, '')
    .replace(/\/index(\[\w+])*$/, '$1')
    .replace(/\[(\w+)]/g, '/:$1')
    .replace(/\/\//g, '/')
    .toLowerCase()
  return path
}

// 路由处理
function routerHandle() {
  let routerMap = {}
  // 通过 keys() 获取文件名列表
  let keys = routers.keys()
  // 生成 routerMap 对象
  keys.forEach(key => {
    let path = pathHandle(key)
    routerMap[path] = {
      path, // 路由配置
      children: [], // 子路由
      isTop: true, // 是否为最上级路由
      key // 相对文件路径
    }
  })
  let routerMapKeys = Object.keys(routerMap)
  // 循环对象,匹配父子关系
  routerMapKeys.forEach(key => {
    let parentPath = key.replace(/\/:\w+$/, '').replace(/\/\w+$/, '')
    let parent = routerMap[parentPath]
    if (parent) {
      routerMap[key].isTop = false
      parent.children.push(routerMap[key])
    }
  })
  let topRouters = []
  // 获取最上级路由
  routerMapKeys.forEach(key => {
    let route = routerMap[key]
    if (route.isTop) {
      topRouters.push(route)
    }
  })
  // 递归填充路由代码
  return childrenRouteHandler(topRouters)
}

// 递归函数
function childrenRouteHandler(items) {
  return items.map(item => {
    if (item.children.length > 0) {
      // routers(item.key).default 通过传入 key 执行 require 函数获取对应的文件内容
      // 配置路由,将子路由(childrenRoute)通过 bind 的方式传入父级路由
      return <Route key={item.path} path={`${item.path}`} component={routers(item.key).default.bind({ childrenRoute: childrenRouteHandler(item.children) })}></Route>
    } else {
      return <Route key={item.path} exact path={`${item.path}`} component={routers(item.key).default}></Route>
    }
  })
}


function App() {

  routerHandle()
  return (
    <Router>
      <div className="App">
        {/* 执行 routerHandle 导入路由 */}
        {routerHandle()}
      </div>
    </Router>
  );
}

export default App;
// src/pages/Home/index.tsx 父级路由
// src/pages/Home/test1.tsx 子路由1
// src/pages/Home/test2.tsx 子路由2
export default function Home(this: any, props: any){
  // 通过 this.childrenRoute 获取到子路由,导入即可
  return (<>Home { this.childrenRoute } </>)
}

补充

require.context

react-router-dom - npm (npmjs.com)

require.context()语法在ts环境下的配置

npm i @types/webpack-env @types/node -D

缺点

目前没有实现,父孙路由关系,如 /aaa 和 /aaa/bbb/ccc,由于 /aaa/bbb/ccc 没有父级,便会自动识别为顶级路由,叶子节点使用了 exact 相当于两个顶级路由,不存在交集。

第二版

React(react-router-dom) 根据路径自动配置路由 延申

第三版

React(react-router-dom) 根据路径自动配置路由 第三版

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React Router是一个用于构建单页面应用程序的库。它提供了一种在React应用程序中管理路由的方式。React Router DOM是React Router的一个扩展,用于在Web应用程序中进行路由React Router DOM 5和React Router DOM 6之间有几个重要的区别: 1. 安装方式:React Router DOM 5使用npm包管理器进行安装,命令为`npm install react-router-dom`。而React Router DOM 6使用yarn进行安装,命令为`yarn add react-router-dom@next`。 2. 路由组件:在React Router DOM 5中,使用`<Route>`组件来定义路由。而在React Router DOM 6中,使用`<Route>`组件的替代方案`<Routes>`来定义路由。 3. 路由匹配方式:React Router DOM 5使用基于路径的匹配方式来确定哪个路由应该被渲染。而React Router DOM 6引入了新的匹配方式,称为元素匹配(element matching),它可以根据组件的类型来匹配路由。 4. 嵌套路由:在React Router DOM 5中,嵌套路由需要使用嵌套的`<Route>`组件来定义。而在React Router DOM 6中,可以使用嵌套的`<Routes>`组件来定义嵌套路由。 5. 动态路由:在React Router DOM 5中,可以通过在路径中使用参数来定义动态路由。而在React Router DOM 6中,可以使用`<Route>`组件的新属性`element`来定义动态路由。 6. 错误处理React Router DOM 5使用`<Switch>`组件来处理路由匹配错误。而React Router DOM 6使用`<Routes>`组件的新属性`fallback`来处理路由匹配错误。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值