react antd后台管理系统路由、导航设计

作为主流框架,本人比较喜欢react风格,引入导入可能多些代码,相比Vue更为完整

选择antd作为web后台管理系统框架,其一是ant的UI好看,其二组件完善

不论是新手还是老手都比较愿意去使用ant,彩蛋事件忽略

本文主要是讲react框架上后台管理系统路由设计,ant并非项目必须

主要使用react-router-dom 4.0模块,

  • 实现一套路由配置同时兼容路由和导航条的渲染,其中借鉴了Vue Router的config的写法
  • 实现登录验证
  • 用户管理权限部分

/* 使用Mobx作为状态管理 */

作为本人设计笔记,也供在线点评

嵌套路由

例:
这里有一个后台管理系统,通常这套系统会有主页、用户管理两个页面,用户管理里面会有用户详情,修改编辑这类
那么我们会定义用户管理页面的path:/user,用户详情/user/detail,单个用户的情况下/user/detail/:id,这样的写法。
当我们用户详情下面再有什么单独页面显示,那么就会出现/user/detail/:id/**这类,那么这种就需要嵌套路由

使用react-router-dom完成嵌套路由,具体写法

<Switch>
      <Route path="/index" />
        <Route path="/user">
              
                <Switch>
                        <Route path="/user/detail/:id" component={ /*子路由组件 */ }></Route>
                        /* 希望路由只针对某个用户,而非针对用户的访问情况,需要跳转到相应上级页面 */
                        <Route render={ () => <Redirect to="/user" /> } />
                </Switch>
        </Route>
</Switch>

以上即为路由的嵌套写法

导航部分:

image.png

如这样,用户管理,下面有其他项,经过分析,路由与导航是可以统一配置的

那么为了统一,方便配置(少量代码,做更多有趣的事),我们会定义一个json,同时去处理路由与nav

简单定义一个RouterConfig.js文件,
export default [
  {
    path : '/home',    //  一级路由path
    meta : '主页',     //  导航名称
    icon : '',      //  所用icon
    role : [],    //  适用权限
    // 所用组件 
    component : sync(() => import( /* webpackChunkName: 'home' */ '@/Pages/Home/index.js')),
    children : [  //二级路由
        {
              path : '/one',  //二级路由path ,react将会渲染为/home/one
              meta : '嵌套1',
              icon : '',
              role : [],
              component : sync(() => import ( /* webpackChunkName: 'home_page_one' */ '@/Pages/Home/one')), 
              children : []
        },
        {
              path : '/two',
              meta : '嵌套2',
              icon : '',
              role : [],
              component : sync(() => import ( /* webpackChunkName: 'home_page_one' */ '@/Pages/Home/two')), 
              children : [],
          },
      ],
  },
  {
            path : '/user',
            meta : '用户',
            icon : '',
            role : [],
            component : sync(() => import( /* webpackChunkName: 'user' */ '@/Pages/User/index.js')),
            children : [
                    {
                        path : '/one',
                        meta : '嵌套1',
                        icon : '',
                        role : [],
                        component : sync(() => import ( /* webpackChunkName: 'user_page_one' */ '@/Pages/User/one')), 
                        children : [],
                    },
                    {
                          path : '/two',
                          meta : '嵌套2',
                          icon : '',
                          role : [],
                          component : sync(() => import ( /* webpackChunkName: 'user_page_two' */ '@/Pages/User/two')),
                          children : [], 
                      },
              ]
        }

]

是不是更像是一个Vue Router 配置呢

直面React-router-dom 路由全部配置
import RouterConfig from 'RouterConfig.js'

class RouterComponent extends React.component {
render () {
        return (
            <Switch>
                {
                    RouterConfig.map(
                        router => {
                            return (
                                <Route
                                    path={ router.path }
                                    key={ router.path }
                                    component={
                                        props => {
                                            return (
                                                <RouteComponent 
                                                    router={ router } 
                                                    { ...props } 
                                                />
                                            )
                                        }
                                    }
                                />
                            )
                        }
                    )
                }
            </Switch>
        )
    }
}
一级路由
export const RouteComponent = props => {
    return (
        <Switch>
            {
                props.router.children.map (
                    router => {
                        return (
                            <Route
                                path={ props.match.url + router.path }
                                key={ router.path }
                                { ...props }
                                component={
                                    npx => {
                                        return (
                                            <RouteChildrenComponent 
                                                router={ router }
                                                { ...npx }
                                            />
                                        )
                                    }
                                }
                            />
                        )
                    }
                )
            }
            {
                <Route 
                    component={ 
                        () => {
                            return <Container { ...props } component={ props.router.component } />
                        } 
                    } 
                /> 
            }
        </Switch>
    )
}
子路由
export const RouteChildrenComponent = props => {
    return (
        <Switch>
            {
                props.router.children.map(
                    npx => {
                        return (
                            <Route
                                path={ npx.path ? props.match.url + npx.path : '' }
                                key={ npx.meta }
                                component={
                                    props => {
                                        return (
                                            <Container { ...props } component={ npx.component } />
                                        )
                                    }
                                }
                            />
                        )
                    }
                )
            }
            {
                props.router.component ? 
                (
                    <Route 
                        render={ 
                            () => {
                                return (
                                    <Container { ...props } component={ props.router.component } /> 
                                )
                            }
                        }
                    />
                ) 
                : <Route render={ () => <Redirect to='/login' /> } />
            }
        </Switch>
    )
}
渲染导航

class MenuComponent extends React.Component {

    render () {
        let collapsed = this.props.store.collapsed
        let store = this.props.store;

        const defaultOpenKeys = router.map( item => item.path )

        return (
            <Menu 
                defaultSelectedKeys={ [ this.props.location.pathname ] }
                theme="dark" 
                defaultOpenKeys={ defaultOpenKeys }
                mode="inline" 
                inlineCollapsed={ collapsed }
            >
                {
                    router.map(
                        npx => {
                            return (
                                <SubMenu 
                                    key={ npx.path } 
                                    title={
                                        <span>
                                            <Icon type={ npx.icon ? npx.icon : 'user' } />
                                            <span>{ npx.meta }</span>
                                        </span>
                                    }
                                >
                                    {
                                       /*这里并未做权限验证,只是做了个基本的应用*/
                                        npx.role === '' || store[npx.role] ? 
                                        <MenuItem
                                            key={ npx.path }
                                            onClick = {
                                                () => this.props.history.push( npx.path )
                                            }
                                        >
                                            { npx.meta }
                                        </MenuItem> : ''
                                    }
                                    { 
                                        npx.children.map( 
                                            item => {
                                            /*这里并未做权限验证,只是做了个基本的应用*/
                                                return (
                                                    store[ item.role ] || item.role === '' ? (
                                                        <Menu.Item 
                                                            key={ npx.path + item.path } 
                                                            onClick={ 
                                                                () => this.props.history.push( npx.path + item.path ) 
                                                            }
                                                        >
                                                            { item.meta }
                                                        </Menu.Item> 
                                                    ) : ''
                                                )
                                            }
                                        )
                                    }
                                    
                                </SubMenu>
                            )
                        }
                    )
                }
            </Menu>
        )
    }
}

一个Vue 路由配置拿到React的小例子,写好配置就是做好渲染就可以啦,so,是需要去看代码的。

git:
https://github.com/wulibaibao/react-antd-demo
个人博客:
https://www.wulibaibao.com

推荐阅读更多精彩内容

  • 我姓付,常有人说,这姓不好,以后做了正职,按常规叫法,听起来依然是副职。每每被人介绍,多数人都还要解释一番。我却满...
    飞常心阅读 456评论 1 3
  • 跑步的酣畅是不跑步的人永远也体会不到的。假如你现在正抱着可乐,吃着薯片吹着空调玩手机,让你出去走上一圈,则如经历炼...
    家有喵星人1阅读 223评论 0 0
  • 家庭有广义和狭义之分:狭义是指一夫一妻制构成的社会单元;广义的则泛指人类进化的不同阶段上的各种家庭利益集团即家族。...
    雷哥说阅读 247评论 4 6
  • 伴着日文《大丈夫》的歌声,我在键盘上敲下了今天推文的第一句话。 刚刚看完朋友小王在自己公众号上发表的“停更告别信”...
    弓水吉阅读 381评论 4 6