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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容

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