一、概述

  参看地址:https://pro.ant.design/docs/router-and-nav-cn

二、原文摘要

  路由和菜单是组织起一个应用的关键骨架,我们的脚手架提供了一些基本的工具及模板,帮助你更方便的搭建自己的路由/菜单。

  如果你想了解更多关于 browserHistory 和 hashHistory,请参看 构建和发布

注意:我们的脚手架依赖 dva@2,路由方面是基于 react-router@4 的实现,在写法以及 API 上与之前的版本有较大不同,所以,在开始前你需要具备一些相关的基础知识。这里给出几篇关键文档:

2.1、基本结构

脚手架通过结合一些配置文件、基本算法及工具函数,搭建好了路由和菜单的基本框架,主要涉及以下几个模块/功能:

  • 路由生成 结合路由信息的配置文件和预设的基本算法,提供了在不同层级文件中自动生成路由列表的能力。

  • 菜单生成 由确定数据结构的菜单配置文件生成,其中的菜单项名称,嵌套路径与路由有一定关联关系。

  • 面包屑 组件 PageHeader 中内置的面包屑也可由脚手架提供的配置信息自动生成。

简单介绍下各个模块的基本思路。

2.1.1、路由

目前在脚手架中,除了顶层路由,其余路由列表都是自动生成,其中最关键的就是中心化配置文件 src/common/router.js,它的主要作用有两个:

  • 配置路由相关信息。如果只考虑生成路由,你只需要指定每条配置的路径及对应渲染组件。

  • 输出路由数据,并将路由数据(routerData)挂载到每条路由对应的组件上。

这样我们得到一个基本的路由信息对象,它的结构大致是这样:

{
'/dashboard/analysis': {
component: DynamicComponent(),
name: '分析页',
},
'/dashboard/monitor': {
component: DynamicComponent(),
name: '监控页',
},
'/dashboard/workplace': {
component: DynamicComponent(),
name: '工作台',
},
}

为了帮助自动生成路由,在 src/utils/utils.js 中提供了工具函数 getRoutes,它接收两个参数:当前路由的 match 路径及路由信息 routerData,主要完成两个工作:

  • 筛选路由信息,筛选的算法为只保留当前 match.path 下最邻近的路由层级(更深入的层级留到嵌套路由中自行渲染),举个例子(每条为一个 route path):

    // 当前 match.path 为 /
    /a // 没有更近的层级,保留
    /a/b // 存在更近层级 /a,去掉
    /c/d // 没有更近的层级,保留
    /c/e // 没有更近的层级,保留
    /c/e/f // 存在更近层级 /c/e,去掉
  • 自动分析路由 exact 参数,除了下面还有嵌套路由的路径,其余路径默认设为 exact。

经过 getRoutes 处理之后的路由数据就可直接用于生成路由列表:

// src/layouts/BasicLayout.js
getRoutes(match.path, routerData).map(item => (
<Route
key={item.key}
path={item.path}
component={item.component}
exact={item.exact}
/>
))

注意:如果你不需要自动生成路由,也可以用 routerData 自行处理。

2.1.2、菜单

菜单信息配置在 src/common/menu.js 中,它的作用是:

  • 配置菜单相关数据,菜单项的跳转链接为配置项及其所有父级配置 path 参数的拼接。

  • 为 src/common/router.js 提供路由名称(name)等数据,根据拼接好的跳转链接来匹配相关路由。

如果你的项目并不需要菜单,你也可以直接在 src/common/router.js 中配置 name 信息。

配置文件输出的菜单数据,可以直接提供给侧边栏组件使用。SiderMenu.js。除了生成菜单,菜单数据还可辅助生成重定向路由等模块,参考 BasicLayout.js#L154

2.1.3、面包屑

  之前提到的路由信息 routerData 可以直接传递给 PageHeader 组件用以生成面包屑,你可以用 props 或者 context 的方式进行传递。脚手架里的示例

2.2、需求示例

2.2.1、新增页面

  脚手架默认提供了两种布局模板:基础布局 - BasicLayout 以及 账户相关布局 - UserLayout,如上文提供的两种图片。

  如果你的页面可以利用这两种布局,那么只需要在路由及菜单配置中增加一条即可:

1》增加路由配置

// src/common/router.js
'/dashboard/test': {
component: dynamicWrapper(app, ['monitor'], () => import('../routes/Dashboard/Test')),
},

2》菜单配置

// src/common/menu.js
const menuData = [{
name: 'dashboard',
icon: 'dashboard', // https://demo.com/icon.png or <Icon type="dashboard" />
path: 'dashboard',
children: [{
name: '分析页',
path: 'analysis',
}, {
name: '监控页',
path: 'monitor',
}, {
name: '工作台',
path: 'workplace',
}, {
name: '测试页',
path: 'test',
}],
}, {
// 更多配置
}];

加好后,会默认生成相关的路由及导航。

2.2.2、新增布局模板

  如果提供的布局不能满足你的要求,就需要自己新建 Layout 模板了。假设有两个新的页面需要使用新模板,你需要先配置好路由及菜单:

1》路由设置

// src/common/router.js
'/new': {
component: dynamicWrapper(app, ['monitor'], () => import('../layouts/NewLayout')),
},
'/new/page1': {
component: dynamicWrapper(app, ['monitor'], () => import('../routes/New/Page1')),
},
'/new/page2': {
component: dynamicWrapper(app, ['monitor'], () => import('../routes/New/Page2')),
},

2》菜单设置

// src/common/menu.js
const menuData = [{
name: '新布局',
icon: 'table',
path: 'new',
children: [{
name: '页面一',
path: 'page1',
}, {
name: '页面二',
path: 'page2',
}],
}, {
// 更多配置
}];

在根路由中增加这组新模板:

// src/router.js
<Router history={history}>
<Switch>
<Route path="/new" render={props => <NewLayout {...props} />} />
<Route path="/user" render={props => <UserLayout {...props} />} />
<Route path="/" render={props => <BasicLayout {...props} />} />
</Switch>
</Router>

然后在你的新模板中,仿照 src/layouts/BasicLayout.js 或 src/layouts/UserLayout.js 生成路由列表即可。

2.3、带参数的路由/菜单

脚手架默认支持带参数的路由、菜单及面包屑配置,直接在路由的 key 以及菜单中的 path 配置即可:

1》路由

// src/common/router.js
'/dashboard/:workplace': {
component: dynamicWrapper(app, ['chart'], () => import('../routes/Dashboard/Workplace')),
},
'/:list/table-list': {
component: dynamicWrapper(app, ['rule'], () => import('../routes/List/TableList')),
},

2》菜单

// src/common/menu.js
const menuData = [{
name: 'dashboard',
icon: 'dashboard',
path: 'dashboard',
children: [{
name: '分析页',
path: 'analysis',
}, {
name: '监控页',
path: 'monitor',
}, {
name: '工作台',
path: ':workplace',
}],
}, {
name: '列表页',
icon: 'table',
path: ':list',
children: [],
}, {
// 更多配置
}];

2.4、嵌套布局

  有时在当前 layout 下还需要嵌套其他布局,例如有几个页面都需要展示同一个模块,你可以把这部分提炼出来变成一个新的布局,再到该布局下生成路由列表。与新增布局模板 的区别,只是不需要将它增加到根路由中。具体可以参照 src/common/router.js /list/search 相关配置,及相关组件文件。

2.5、嵌套路由同级展示

  脚手架默认使用工具函数 getRoutes 对 routerData 进行处理,然后生成路由列表,根据基本算法,在每一级组件中只会渲染当前 match.path 下最邻近的路由,所以,如果你要实现嵌套路由的同级展示(如:将 /list/search 和 /list/search/projects 在同一个地方渲染),就需要手动获取该路由的数据并添加在合适的地方。

{/* src/layouts/BasicLayout.js 类比你的上层 layout 组件 */}
<Content style={{ margin: '24px 24px 0', height: '100%' }}>
<div style={{ minHeight: 'calc(100vh - 260px)' }}>
<Switch>
{/* 默认生成的路由列表,不包含 /list/search/projects */}
{
getRoutes(match.path, routerData).map(item => (
<Route
key={item.key}
path={item.path}
component={item.component}
exact={item.exact}
/>
))
}
{/* 补充 /list/search/projects 的路由 */}
<Route exact path="/list/search/projects" component={routerData['/list/search/projects'].component} />
<Redirect exact from="/" to="/dashboard/analysis" />
<Route render={NotFound} />
</Switch>
</div>
</Content>

同时在嵌套 layout 的文件中去掉这一条路由(如果还有下层路由需要 render)。

{/* src/routes/List/List.js 类比你的嵌套 layout 组件 */}
<Switch>
{
getRoutes(match.path, routerData).filter(item => item.path !== '/list/search/projects').map(item =>
(
<Route
key={item.key}
path={item.path}
component={item.component}
exact={item.exact}
/>
)
)
}
</Switch>

2.6、隐藏菜单

如果需要隐藏某条菜单项,可以在该条数据中增加 hideInMenu 参数。

hideInMenu: true,  // 隐藏该条,或隐藏该组

2.7、隐藏面包屑

如需隐藏面包屑中的某个层级,可以增加 hideInBreadcrumb 属性。

// src/common/router.js
'/dashboard/analysis': {
component: dynamicWrapper(app, ['chart'], () => import('../routes/Dashboard/Analysis')),
hideInBreadcrumb: true, // 隐藏该条
},
'/dashboard/monitor': {
component: dynamicWrapper(app, ['monitor'], () => import('../routes/Dashboard/Monitor')),
},

2.8、关于 dynamicWrapper

import dynamic from 'dva/dynamic';

// wrapper of dynamic
const dynamicWrapper = (app, models, component) => dynamic({
app,
// eslint-disable-next-line no-underscore-dangle
models: () => models.filter(m => !app._models.some(({ namespace }) => namespace === m)).map(m => import(`../models/${m}.js`)),
// add routerData prop
component: () => {
const routerData = getRouterData(app);
return component().then((raw) => {
const Component = raw.default || raw;
return props => <Component {...props} routerData={routerData} />;
});
},
});import dynamic from 'dva/dynamic'; // wrapper of dynamic
const dynamicWrapper = (app, models, component) => dynamic({
app,
// eslint-disable-next-line no-underscore-dangle
models: () => models.filter(m => !app._models.some(({ namespace }) => namespace === m)).map(m => import(`../models/${m}.js`)),
// add routerData prop
component: () => {
const routerData = getRouterData(app);
return component().then((raw) => {
const Component = raw.default || raw;
return props => <Component {...props} routerData={routerData} />;
});
},
});

为了代码的简洁性,我们对 dva/dynamic 进行了二次封装,需要注意的是这里使用了 Webpack Code Splitting 的动态 importdva 的 dynamic 方法已经帮我们封装好了 Promise 动态加载的相关事宜,所以我们只需要直接使用即可。

ant design pro (三)路由和菜单的更多相关文章

  1. Ant Design Pro 学习二 新建菜单-布局

    新建布局,注意格式: src/common/nav.js 中增加 { component: dynamicWrapper(app, [], () => import('/path/to/NewL ...

  2. 使用ant design pro搭建项目

    脚手架搭建 git clone --depth=1 https://github.com/ant-design/ant-design-pro.git my-project 然后 cd my-proje ...

  3. Ant Design Pro路由传值

    Ant Design Pro 路由传值 了解Ant Design Pro组件间通讯原理的小伙伴肯定都知道,两个页面之间可以通过Models进行传值,在以往的传值过程中,我都是直接将需要的值直接一股脑的 ...

  4. 【后台管理系统】—— Ant Design Pro入门学习&项目实践笔记(三)

    前言:前一篇记录了[后台管理系统]目前进展开发中遇到的一些应用点,这一篇会梳理一些自己学习Ant Design Pro源码的功能点.附:Ant Design Pro 在线预览地址. Dashboard ...

  5. Ant Design Pro快速入门

    在上一篇文章中,我们介绍了如何构建一个Ant Design Pro的环境. 同时讲解了如何启动服务并查看前端页面功能. 在本文中,我们将简单讲解如何在Ant Design Pro框架下实现自己的业务功 ...

  6. Ant Design Pro (中后台系统)教程

    一.概念:https://pro.ant.design/docs/getting-started-cn(官方网站) 1.Ant Design Pro 是什么:  https://www.cnblogs ...

  7. ant design pro (十三)advanced 错误处理

    一.概述 原文地址:https://pro.ant.design/docs/error-cn 二.详细 2.1.页面级报错 2.1.1.应用场景 路由直接引导到报错页面,比如你输入的网址没有匹配到任何 ...

  8. ant design pro(一)安装、目录结构、项目加载启动【原始、以及idea开发】

    一.概述 1.1.脚手架概念 编程领域中的“脚手架(Scaffolding)”指的是能够快速搭建项目“骨架”的一类工具.例如大多数的React项目都有src,public,webpack配置文件等等, ...

  9. 初探ant design pro

    1.增加路由子页面&配置菜单 因为ant design pro采取的是umi路由配置,所以只要在对应的文件夹下新建相关的文件夹以及文件,它会自动解析.按照如下的步骤做即可 PS.如果想要给菜单 ...

  10. Ant Design Pro 脚手架+umiJS 实践总结

    一.简介 1.Ant Design Pro Ant Design Pro是一款搭建中后台管理控制台的脚手架 ,基于React,dva.js,Ant Design (1)其中dva主要是控制数据流向,是 ...

随机推荐

  1. [jzyzoj2021]lca模板题

    查找最近公共祖先...我也不知道这东西有什么用,在线写法,非常之慢.... 存代码 #include<cstdio> #include<iostream> #include&l ...

  2. BZOJ3238 [Ahoi2013]差异 SA+单调栈

    题面 戳这里 题解 考虑把要求的那个东西拆开算,前面一个东西像想怎么算怎么算,后面那个东西在建出\(height\)数组后相当于是求所有区间\(min\)的和*2,单调栈维护一波即可. #includ ...

  3. HDU 6119 小小粉丝度度熊(Two pointers)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6119 [题目大意] 给出一些签到区间和一些补签卡,问可以创造的最长连续签到区间 [题解] 如果我们 ...

  4. [转]php-fpm - 启动参数及重要配置详解

    约定几个目录/usr/local/php/sbin/php-fpm/usr/local/php/etc/php-fpm.conf/usr/local/php/etc/php.ini 一,php-fpm ...

  5. VK Cup 2016 - Qualification Round 1 (Russian-Speaking Only, for VK Cup teams) A. Voting for Photos 水题

    A. Voting for Photos 题目连接: http://www.codeforces.com/contest/637/problem/A Description After celebra ...

  6. PAT甲级1045. Favorite Color Stripe

    PAT甲级1045. Favorite Color Stripe 题意: 伊娃正在试图让自己的颜色条纹从一个给定的.她希望通过剪掉那些不必要的部分,将其余的部分缝合在一起,形成她最喜欢的颜色条纹,以保 ...

  7. 源码分析:动态分析 Linux 内核函数调用关系

    源码分析:动态分析 Linux 内核函数调用关系 时间 2015-04-22 23:56:07  泰晓科技 原文  http://www.tinylab.org/source-code-analysi ...

  8. .net程序保护方式大观

    .net软件保护方式大观 最近调试一个运行于.net 2.0下的软件,发现该软件使用的保护方式很具有代表性,基本囊括了现在.net下的所有保护措施.实践证明,这些保护措施就像全真七子,单打独斗功力差了 ...

  9. mmap函数使用

    UNIX网络编程第二卷进程间通信对mmap函数进行了说明.该函数主要用途有三个:1.将一个普通文件映射到内存中,通常在需要对文件进行频繁读写时使用,这样用内存读写取代I/O读写,以获得较高的性能:2. ...

  10. linux中的dup()系统调用

    参考1:http://www.blogjava.net/lihao336/archive/2011/12/13/366231.html 在linux纷繁复杂的内核代码中,sys_dup()的代码也许称 ...