react 路由配置以及封装

本文详细介绍了如何在React项目中使用BrowserRouter和Layout组件实现路由判断登录状态,并演示了如何配置一级和二级路由,包括菜单动态渲染与权限控制。通过实例展示了如何在App、IsLogin和Layout组件间进行交互,以及在router.js中的路由配置方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

react 路由配置以及封装

1、新建App.tsx文件
import React, { Component } from 'react'
import IsRouter from './router/islogin'
class App extends Component {
render() {
     return (
         <IsRouter/>
     );
 }
}

export default App;

IsRouter是用来判断其是否登录的js文件,我通常把它放在router文件夹下,看个人习惯。

2、islogin.jsx内容如下

在这里插入图片描述

 import React, { Component } from 'react'
import {BrowserRouter as Router,Route} from 'react-router-dom'
import Layout from '../layout/layout'
export default class Islogin extends Component{
      // constructor(props) {
      //       super(props);
      //       this.state = {  };
      //   }
      render(){
          return(
                <Router>
                    {/* <Route path="/login" component={Login}/> */}
                      <Route path="/*"  render={()=><Layout/>}/>
                     
                </Router>
          )
      }
}

本项目只是一个模板,因此忽略了登录这块直接展示Laout组件,也就是我们常见的后台管理系统模块。

3、layout页面展示

页面是仿照antd pro后台管理系统案例做的,
在这里插入图片描述

import HeaderBar from '../component/Header';
import React, { Component } from 'react'
import {Redirect,Route,Link,Switch } from 'react-router-dom'

import {Layout,Menu} from 'antd';
 import router from '../router/router'  
import Footer from '../component/Footer'
import logo from '../assets/img/logo192.png';
import 'antd/dist/antd.css';
import './layout.scss'
const {Sider,Content} = Layout;
const { SubMenu } = Menu;



let route = router.map((item)=>{
       return item.path;
})

const SliderMenu = ()=>{
       let pathname = window.location.pathname;
       if(pathname ==='/'){
              pathname = '/dashboard/Analysis';
       }
     
      let selectedKey =  pathname  //设置defaultSelectedKeys
       let openKey = "/"+ pathname.split("/")[1] //截取二级路由的一级路径,设置defaultOpenKeys
      
       const [openKeys, setOpenKeys] = React.useState([openKey]); 
     
       const onOpenChange = (keys:any) => {
             
              const latestOpenKey = keys.find((key:any) => openKeys.indexOf(key) === -1);
              if (route.indexOf(latestOpenKey) === -1) {
                setOpenKeys(keys);
              } else {
                setOpenKeys(latestOpenKey ? [latestOpenKey] : []);
              }
       };

       //遍历左侧餐单
       const renderMenu = (menus:any)=>{
              let Menus = menus.map((item:any)=>{
                     if(item.routes){
                            return <SubMenu key={item.path} title={
                                     <span>
                                            {item.icon}
                                            <span>{item.title}</span>
                                     </span>
                            }>
                                 {renderMenu(item.routes)}
                            </SubMenu>
                     }else{
                         
                         return <Menu.Item key={item.path} icon={item.icon ? item.icon:'' }>
                                  <Link to={item.path}>{item.title}</Link> 
                                </Menu.Item>
                     }
              })
            
              return Menus;
       }
           
     return (
               <Menu theme="dark" mode="inline" 
                     defaultOpenKeys={ [openKey] }
                     defaultSelectedKeys={ [selectedKey] }
                     openKeys={openKeys} 
                     onOpenChange={onOpenChange}
                     >
                     {renderMenu(router)}
                     
              </Menu>
     )
}

class BasicLayout extends Component {
     
    state={
         collapsed:false,
         defaultOpenKeys: ['/dashboard'],       // 默认展开
         defaultSelectedKeys: ['/dashboard/Analysis'],   // 默认选中
    }
    //控制左侧菜单收缩
    toggle=()=>{
         
           this.setState({
                  collapsed:!this.state.collapsed
           })
          
    }
    
    //渲染路由
    forList=(List:any[])=>{
       
         var arr= List.map((item)=>{
                if(item.routes){
                       return item.routes.map((each:any)=>{
                              return <Route exact key={each.path} path={each.path} component={each.component}></Route>
                       })
                }else{
                    return <Route exact key={item.path} path={item.path} component={item.component}></Route>
                }
         })
    
         let newarr:any[] =[];
             arr.forEach(item=>{
                    if(Object.prototype.toString.call(item) === '[object Array]'){
                           item.forEach((each:any)=>{
                                  newarr.push(each);
                           })
                    }else{
                          newarr.push(item);
                    }
             })
         
         return newarr;
    }
   
    componentDidMount(){
      
    }
   
     render() {
              let name;
              if (!this.state.collapsed) {
                 name = <span className="name">React管理后台</span>;
              }
             
            
                
             
          return (
                 <Layout>
                       <Sider trigger={null} collapsible collapsed={this.state.collapsed}  style={{ height: '100vh',zIndex:100}} onCollapse={ this.toggle } width={208}>
                            <div className="logo">
                                     <img src={logo} alt="" className="custom-img"/>
                                     {name}
                            </div>
                            <SliderMenu/>
                       </Sider>
                       <Layout className="site-layout">
                            
                              <HeaderBar toggle={this.toggle}></HeaderBar>
                              <Content
                                   className="site-layout-background"
                                   style={{
                                       height:'auto',
                                       minHeight: 'auto'
                                        }}
                                       >
                                    <div className="ant-pro-grid-content">
                                       <div className="ant-pro-grid-content-children">
                                          <Switch>
                                          
                                          {this.forList(router)}
                                          <Redirect from="/*" to="/dashboard/Analysis"></Redirect>
                                          </Switch>   
                                      </div>
                                   </div>
                                         
                              </Content>
                              <Footer/>
                         </Layout>
                      
                 </Layout>
          );
     }
}

export default BasicLayout;

每一个模块代码中可以明确知道是干什么的,具体就不详细说了。

4、router.js

router.js和vue封装的router.js效果差不多,只不过是react需要自己封装。

// import basicLayout from '../layout/layout'
import Analysis from '../page/dashboard/Analysis'
import Monitor from '../page/dashboard/Monitor'
import Workbench from '../page/dashboard/Workbench'
import Personal from '../page/Personal'
import Stepform from '../page/form/Stepform'
import Advanceform from '../page/form/Advanceform'
import Tablelist from '../page/list/Tablelist'
import Basiclist from '../page/list/Basiclist'
import {
    OrderedListOutlined,
    UserOutlined,
    FormOutlined,
    SmileOutlined
  } from '@ant-design/icons';

let  routes=[
    {
        title:'Dashboard',
        path:'/dashboard',
         icon: <SmileOutlined/>,
        routes:[
            {
                title:'分析页',
                id:'1-2',
                path:'/dashboard/Analysis',
                component:Analysis
            },
           
            {
             title:'监控页',
             id:'1-1',
             path:'/dashboard/Monitor',
             component:Monitor
            
            },
            {
                title:'工作台',
                id:'1-3',
                path:'/dashboard/Workbench',
                component: Workbench
             },
           
        ]
    },
    {
        title:'表单页',
       path:'/form',
        icon: <FormOutlined />,
        routes:[
            {
                title:'分布表单',
               path:'/form/step-form',
                component:Stepform
            },
            {
             title:'高级表单',
            path:'/form/advanced-form',
            component:Advanceform
            },
          
        ]
    },
    {
        title:'列表页',
        path:'/list',
        icon: <OrderedListOutlined />,
        // component:Personal
        routes:[
            {
                title:'查询表格',
                path:'/list/table-list',
                component:Tablelist
            },
            {
                title:'标准列表',
                path:'/list/basic-list',
                component:Basiclist
            }
        ]
    },
    {
        title:'个人页',
        path:'/personal',
        icon: <UserOutlined/>,
        component:Personal
    }
]
 export default routes;

这里需要强调一点的是上述代码都是一级路由,如果想配二级路由,那在每一个层级直接配置就行,废话不多说,上案例

 {
     title:'Dashboard',
     path:'/dashboard',
      icon: <SmileOutlined/>,
     routes:[
         {
             title:'分析页',
             id:'1-2',
             path:'/dashboard/Analysis',
             component:Analysis,
             exact:false, //这个一定得设置成false非严格模式,如果设置成true就会导致页面路由匹配不到页面空白不会报错
             //假设这个层级下面还有二级理由analysicdetail
             children:[
              {
		          title:'分析详情页',
		          id:'1-2-1',
		          path:'/dashboard/Analysis/analysicdetail',
		          component:Analysicdetail,
		          exact:true //这个可以设置成严格模式
		         
		        },
             ]
         },
        
         {
          title:'监控页',
          id:'1-1',
          path:'/dashboard/Monitor',
          component:Monitor
         
         },
         {
             title:'工作台',
             id:'1-3',
             path:'/dashboard/Workbench',
             component: Workbench
          },
        
     ]
 },

接下来在路由渲染的时候修改代码

 import config from './router/router'
 let router =  config.routes.map((item,key)=>{
  
  return <Route exact={item.exact}  path={item.path} key={key} render={
      props =>{
          if(item.children){
              return  <item.component {...props} routes={item.children} />
          }else{
            return  <item.component {...props} />
          }
      }
  }/>
}) 

上面是一级路由渲染,二级路由渲染同上面有点类似

  //渲染路由
    forList=(List)=>{
       var arr= List.map((item)=>{
                if(item.children){
                       return item.children.map((each)=>{
                              return <Route exact={each.exact} key={each.path} path={each.path} component={each.component}></Route>
                       })
                }else{
                    return <Route exact={each.exact} key={item.path} path={item.path} component={item.component}></Route>
                }
         })
     return arr;
    }
 componentDidMount(){
    let router = this.props.routes;//有点基础的前端应该知道item.children把值传给了routes,那在二级页面上就能够拿到对应导航下的所有路由,不明白的可以打印一下看routers是什么。
    this.forList(router);
 }
 render(){
   let routes = this.props;
    return (
          {
		        this.forList(routes)//componentDidMount可以不要,效果和render方法渲染的效果相同,只不过为了看起来更加容易理解,两种方式任选一种。
		   }
    )
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值