基于React实现路由配置的学习记录,弄懂不同导入方式下实现Route的配置

之前弄react项目配置路由都是直接在App.js中配的,像这样

<Routes>
      <Route path='/' element={<Backstage url='/index'></Backstage>}></Route>
      <Route path='/login' element={<Login></Login>}></Route>
</Routes>

于是想到能不能实施一种类似于vue的路由配置,将路由的配置信息像vue的格式一样写在一个文件内,类似该格式

{
    path:'/index',
    name:'index',
    component:()=>import('@/views/index/index.vue'),
},

我认为要弄懂该实现方式主要在于如何将component转换成Route的element或Component属性,以导入Index并在Route中使用为例

<Route path='/index' element={<Index></Index>}></Route>
<Route path='/index' Component={Index}></Route>{/* {等价于} */}

相比之下会发现Index是一个funtion类型的(typeof 为function),Index标签是一个JSX.Element类型的,那么这之间该如何转换呢?通过生成JSX.Element的React方法进行转换,但这里我不太懂的是React.createElement第一个参数type应该是string,但是Index却是function是怎么一回事

React.createElement(Index)

接下来使用j两种导入方式。通过控制台输出发现前者为Promise后者为一个object,将Promise通过then输出值发现与后者相同,后者object中的default值与Index相同

import('./views/Index/index');
require('./views/Index/index');

了解以上便可以实现路由的配置功能,基于后台项目常见的一个登录页与复数页面但是使用同一ui架构的方式设想路由,将以view来区分登录与主页,将页面按照分类menu,区分多个页面page;细化下,他们之间拥有共同属性url和name,不同的将是子元素与页面;view是必然拥有页面的但是不一定有子页面,menu为第二层作为分类但是也可能不进行分类的单一页面,因此有可能存在子页面和页面,page第三层只有页面,没有子页面;有以下代码

// 对应页面的object
interface element{
    default:string
}
// 公共元素
interface all_common{
    url:string,
    name:string
}
// 子页面
interface route extends all_common{
    element:element,
}
// 基础页面
interface view extends route{
    children?:Array<menu>
}
// 菜单
interface menu extends all_common{
    element?:element,
    children?:Array<route>
}
// 菜单与子页面配置
const pages:Array<menu> = [
    {
        url:'/index',
        name:'',
        element:require('../pages/Index/index')
    }
]
// 基础页面配置
const routes:Array<view> = [
    {
        url:'/login',
        name:'用户登录',
        element:require('../views/Login/login')
    },
    {
        url:'/',
        name:'主页',
        element:require('../views/Index/index'),
        children:pages
    }
]

export default routes;

将路由内容解析有以下代码,将子页面均将内容以props传入view的页面中进一步进行处理

import React, { useEffect, useState } from 'react';
import { Route,Routes } from 'react-router-dom';
import routes from './utils/router';

function App() {
  // 路由配置导入并解析
  let [routelist,setroutelist] = useState<Array<JSX.Element>>();
  useEffect(()=>{
    // 定义JSX.Element的数组
    let list:Array<JSX.Element> = [];
    // view遍历,判断是否存在子页面,有则继续遍历
    routes.forEach((ve,vi)=>{
      if(ve.children){
        // 判断是否存在子元素与页面,存在子元素继续遍历,存在页面则使用view的页面,并将内容作为props导入
        // 这里分开判断主要是是否点击菜单时也会展示页面,否则使用else if即可
        ve.children.forEach((me,mi)=>{
          if(me.children){
            // 第三层遍历使用view页面并且处理url和name,以细化的方式处理,将内容作为props导入
            me.children.forEach((pe,pi)=>{
              list.push(<Route path={me.url+pe.url} key={pi} element={React.createElement(ve.element.default,{
                url:me.url+pe.url,
                name:`${me.name}/${pe.name}`,
                element:pe.element
              })}></Route>)
            })
          }
          if(me.element) list.push(<Route path={me.url} key={mi} element={React.createElement(ve.element.default,me)}></Route>)
        })
      }
      list.push(<Route path={ve.url} key={vi} element={React.createElement(ve.element.default)}></Route>)
    })
    setroutelist(list);
  },[routes])
  return (
    <div className="App">
      <Routes>
        {
          routelist
        }
      </Routes>
    </div>
  );
}

export default App;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值