
在config.js文件中进行配置:
export default {
plugins: [
['umi‐plugin‐react', {
dva: true, // 开启dva功能
antd: true // 开启Ant Design功能
}]
]
};
创建MyTabs.js文件:
import React from 'react'
import {Tabs} from 'antd'
const TabPane = Tabs.TabPane;
const callback = (key) => {
console.log(key);
}
class MyTabs extends React.Component {
render() {
return (
<Tabs defaultActiveKey="1" onChange={callback}>
<TabPane tab="Tab 1" key="1">Content of Tab Pane
1</TabPane>
<TabPane tab="Tab 2" key="2">Content of Tab Pane
2</TabPane>
<TabPane tab="Tab 3" key="3">Content of Tab Pane
3</TabPane>
</Tabs>
)
}
}
export default MyTabs;


在src目录下创建layouts目录,并且在layouts目录下创建index.js文件,写入内容:
import React from 'react'
import { Layout } from 'antd';
const { Header, Footer, Sider, Content } = Layout;
class BasicLayout extends React.Component{
render(){
return (
<Layout>
<Sider>Sider</Sider>
<Layout>
<Header>Header</Header>
<Content>Content</Content>
<Footer>Footer</Footer>
</Layout>
</Layout>
);
}
}
export default BasicLayout;
需要特别说明的是,在umi中约定的目录结构中,layouts/index.js文件将被作为全
局的布局文件
接下来,配置路由:(非必须)
config.js文件
export default {
plugins: [
['umi‐plugin‐react', {
dva: true, // 开启dva功能
antd: true // 开启Ant Design功能
}]
],
routes: [{
path: '/',
component: '../layouts' //配置布局路由
}]
};

首先,需要在布局文件中,将Content内容替换成{this.props.children},意思是引入传
递的内容。
import React from 'react'
import { Layout } from 'antd';
const { Header, Footer, Sider, Content } = Layout;
class BasicLayout extends React.Component{
render(){
return (
<Layout>
<Sider>Sider</Sider>
<Layout>
<Header>Header</Header>
<Content>{this.props.children}</Content>
<Footer>Footer</Footer>
</Layout>
</Layout>
);
}
}
export default BasicLayout;
接下来配置路由(注意,在布局路由下面进行配置)
说明:下面的路由配置,是表明你需要通过手动配置的方式上进行访问页面,而不
采用umi默认路由

import React from 'react'
import { Layout } from 'antd';
const { Header, Footer, Sider, Content } = Layout;
class BasicLayout extends React.Component{
render(){
return (
<Layout>
<Sider width={256} style={{ minHeight: '100vh', color:
'white' }}>
Sider
</Sider>
<Layout>
<Header style={{ background: '#fff', textAlign:
'center', padding: 0 }}>Header</Header>
<Content style={{ margin: '24px 16px 0' }}>
<div style={{ padding: 24, background: '#fff',
minHeight: 360 }}>
{this.props.children}
</div>
</Content>
<Footer style={{ textAlign: 'center' }}>后台系统 ©2018
Created by 黑马程序员</Footer>
</Layout>
</Layout>
);
}
}
export default BasicLayout;

import React from 'react'
import {Layout, Menu, Icon} from 'antd';
const {Header, Footer, Sider, Content} = Layout;
const SubMenu = Menu.SubMenu;
class BasicLayout extends React.Component {
constructor(props){
super(props);
this.state = {
collapsed: false,
}
}
render() {
return (
<Layout>
<Sider width={256} style={{minHeight: '100vh', color:
'white'}}>
<div style={{ height: '32px', background:
'rgba(255,255,255,.2)', margin: '16px'}}/>
<Menu
defaultSelectedKeys={['2']}
defaultOpenKeys={['sub1']}
mode="inline"
theme="dark"
inlineCollapsed={this.state.collapsed}
>
<Menu.Item key="1">
<Icon type="pie‐chart"/>
<span>Option 1</span>
</Menu.Item>
<Menu.Item key="2">
<Icon type="desktop"/>
<span>Option 2</span>
</Menu.Item>
<Menu.Item key="3">
<Icon type="inbox"/>
<span>Option 3</span>
</Menu.Item>
<SubMenu key="sub1" title={<span><Icon
type="mail"/><span>Navigation One</span></span>}>
<Menu.Item key="5">Option 5</Menu.Item>
<Menu.Item key="6">Option 6</Menu.Item>
<Menu.Item key="7">Option 7</Menu.Item>
<Menu.Item key="8">Option 8</Menu.Item>
</SubMenu>
<SubMenu key="sub2" title={<span><Icon
type="appstore"/><span>Navigation Two</span></span>}>
<Menu.Item key="9">Option 9</Menu.Item>
<Menu.Item key="10">Option 10</Menu.Item>
<SubMenu key="sub3" title="Submenu">
<Menu.Item key="11">Option 11</Menu.Item>
<Menu.Item key="12">Option 12</Menu.Item>
</SubMenu>
</SubMenu>
</Menu>
</Sider>
<Layout>
<Header style={{background: '#fff', textAlign:
'center', padding: 0}}>Header</Header>
<Content style={{margin: '24px 16px 0'}}>
<div style={{padding: 24, background: '#fff',
minHeight: 360}}>
{this.props.children}
</div>
</Content>
<Footer style={{textAlign: 'center'}}>后台系统 ©2018
Created by 黑马程序员</Footer>
</Layout>
</Layout>
);
}
}
export default BasicLayout;

在src目录下创建user目录,并且在user目录下创建UserAdd.js和UserList.js文件,用于
模拟实现新增用户和查询用户列表功能
UserAdd.js:
import React from 'react'
class UserAdd extends React.Component{
render(){
return (
<div>新增用户</div>
);
}
}
export default UserAdd;
UserList.js:
import React from 'react'
class UserList extends React.Component{
render(){
return (
<div>用户列表</div>
);
}
}
export default UserList;
配置路由
export default {
plugins: [
['umi‐plugin‐react', {
dva: true, // 开启dva功能
antd: true // 开启Ant Design功能
}]
],
routes: [{
path: '/',
component: '../layouts', //配置布局路由
routes: [
{
path: '/myTabs',
component: './myTabs'
},
{
path: '/user',
routes: [
{
path: '/user/list',
component: './user/UserList'
},
{
path: '/user/add',
component: './user/UserAdd'
}
]
}
]
}]
};
为菜单添加链接:
import React from 'react'
import {Layout, Menu, Icon} from 'antd';
import Link from 'umi/link';
const {Header, Footer, Sider, Content} = Layout;
const SubMenu = Menu.SubMenu;
class BasicLayout extends React.Component {
constructor(props){
super(props);
this.state = {
collapsed: false,
}
}
render() {
return (
<Layout>
<Sider width={256} style={{minHeight: '100vh', color:
'white'}}>
<div style={{ height: '32px', background:
'rgba(255,255,255,.2)', margin: '16px'}}/>
<Menu
defaultSelectedKeys={['1']}
defaultOpenKeys={['sub1']}
mode="inline"
theme="dark"
inlineCollapsed={this.state.collapsed}
>
<SubMenu key="sub1" title={<span><Icon
type="user"/><span>用户管理</span></span>}>
<Menu.Item key="1">
<Link to="/user/list">用户列表</Link>
</Menu.Item>
<Menu.Item key="2">
<Link to="/user/add">新增用户</Link>
</Menu.Item>
</SubMenu>
</Menu>
</Sider>
<Layout>
<Header style={{background: '#fff', textAlign:
'center', padding: 0}}>Header</Header>
<Content style={{margin: '24px 16px 0'}}>
<div style={{padding: 24, background: '#fff',
minHeight: 360}}>
{this.props.children}
</div>
</Content>
<Footer style={{textAlign: 'center'}}>后台系统 ©2018
Created by 黑马程序员</Footer>
</Layout>
</Layout>
);
}
}
export default BasicLayout;


改造UserList.js页面:
import React from 'react'
import {Table, Divider, Tag, Pagination } from 'antd';
const {Column} = Table;
const data = [{
key: '1',
name: '张三',
age: 32,
address: '上海市',
tags: ['程序员', '帅气'],
}, {
key: '2',
name: '李四',
age: 42,
address: '北京市',
tags: ['屌丝'],
}, {
key: '3',
name: '王五',
age: 32,
address: '杭州市',
tags: ['高富帅', '富二代'],
}];
class UserList extends React.Component {
render() {
return (
<div>
<Table dataSource={data} pagination=
{{position:"bottom",total:500,pageSize:10, defaultCurrent:3}}>
<Column
title="姓名"
dataIndex="name"
key="name"
/>
<Column
title="年龄"
dataIndex="age"
key="age"
/>
<Column
title="地址"
dataIndex="address"
key="address"
/>
<Column
title="标签"
dataIndex="tags"
key="tags"
render={tags => (
<span>
{tags.map(tag => <Tag color="blue" key=
{tag}>{tag}</Tag>)}
</span>
)}
/>
<Column
title="操作"
key="action"
render={(text, record) => (
<span>
<a href="javascript:;">编辑</a>
<Divider type="vertical"/>
<a href="javascript:;">删除</a>
</span>
)}
/>
</Table>
</div>
);
}
}
export default UserList;

model的实现:UserListData.js
import request from "../util/request";
export default {
namespace: 'userList',
state: {
list: []
},
effects: {
*initData(params, sagaEffects) {
const {call, put} = sagaEffects;
const url = "/ds/user/list";
let data = yield call(request, url);
yield put({
type : "queryList",
data : data
});
}
},
reducers: {
queryList(state, result) {
let data = [...result.data];
return { //更新状态值
list: data
}
}
}
}
修改UserList.js中的逻辑
import React from 'react';
import { connect } from 'dva';
import {Table, Divider, Tag, Pagination } from 'antd';
const {Column} = Table;
const namespace = 'userList';
@connect((state)=>{
return {
data : state[namespace].list
}
}, (dispatch) => {
return {
initData : () => {
dispatch({
type: namespace + "/initData"
});
}
}
})
class UserList extends React.Component {
componentDidMount(){
this.props.initData();
}
render() {
return (
<div>
<Table dataSource={this.props.data} pagination=
{{position:"bottom",total:500,pageSize:10, defaultCurrent:3}}>
<Column
title="姓名"
dataIndex="name"
key="name"
/>
<Column
title="年龄"
dataIndex="age"
key="age"
/>
<Column
title="地址"
dataIndex="address"
key="address"
/>
<Column
title="标签"
dataIndex="tags"
key="tags"
render={tags => (
<span>
{tags.map(tag => <Tag color="blue" key=
{tag}>{tag}</Tag>)}
</span>
)}
/>
<Column
title="操作"
key="action"
render={(text, record) => (
<span>
<a href="javascript:;">编辑</a>
<Divider type="vertical"/>
<a href="javascript:;">删除</a>
</span>
)}
/>
</Table>
</div>
);
}
}
export default UserList;
mock数据:MockListData.js
export default {
'get /ds/list': function (req, res) {
res.json({
data: [1, 2, 3, 4],
maxNum: 4
});
},
'get /ds/user/list': function (req, res) {
res.json([{
key: '1',
name: '张三1',
age: 32,
address: '上海市',
tags: ['程序员', '帅气'],
}, {
key: '2',
name: '李四',
age: 42,
address: '北京市',
tags: ['屌丝'],
}, {
key: '3',
name: '王五',
age: 32,
address: '杭州市',
tags: ['高富帅', '富二代'],
}]);
}
}


下载地址:https://github.com/ant-design/ant-design-pro
我们使用资料中提供的,已经下载好的文件:ant-design-pro-master.zip
第一步:将ant-design-pro-master.zip解压到任意目录,比如F:\code\ant-design-pro-master

第二步,导入项目到Idea中
第三步:进行初始化以及启动
tyarn install #安装相关依赖
tyarn start #启动服务

默认的菜单是不能直接投入到项目开发的,所以,我们需要搞清楚如何自定义菜单和路
由。在pro中,菜单和路由,在router.config.js配置文件中进行管理
打开router.config.js后,可以看出,pro提供了有2套路由(布局),分别是/user和/

/user的布局:

接下来,我们先重点关注,/路由

routes: [
// dashboard
{ path: '/', redirect: '/dashboard/analysis' },
{
path: '/dashboard',
name: 'dashboard',
icon: 'dashboard',
routes: [
{
path: '/dashboard/analysis',
name: 'analysis',
component: './Dashboard/Analysis',
},
{
path: '/dashboard/monitor',
name: 'monitor',
component: './Dashboard/Monitor',
},
{
path: '/dashboard/workplace',
name: 'workplace',
component: './Dashboard/Workplace',
},
],
},
// forms
{
path: '/form',
icon: 'form',
name: 'form',
routes: [
{
path: '/form/basic-form',
name: 'basicform',
component: './Forms/BasicForm',
},
{
path: '/form/step-form',
name: 'stepform',
component: './Forms/StepForm',
hideChildrenInMenu: true,
routes: [
{
path: '/form/step-form',
name: 'stepform',
redirect: '/form/step-form/info',
},
{
path: '/form/step-form/info',
name: 'info',
component: './Forms/StepForm/Step1',
},
{
path: '/form/step-form/confirm',
name: 'confirm',
component: './Forms/StepForm/Step2',
},
{
path: '/form/step-form/result',
name: 'result',
component: './Forms/StepForm/Step3',
},
],
},
{
path: '/form/advanced-form',
name: 'advancedform',
authority: ['admin'],
component: './Forms/AdvancedForm',
},
],
},
// list
{
path: '/list',
icon: 'table',
name: 'list',
routes: [
{
path: '/list/table-list',
name: 'searchtable',
component: './List/TableList',
},
{
path: '/list/basic-list',
name: 'basiclist',
component: './List/BasicList',
},
{
path: '/list/card-list',
name: 'cardlist',
component: './List/CardList',
},
{
path: '/list/search',
name: 'searchlist',
component: './List/List',
routes: [
{
path: '/list/search',
redirect: '/list/search/articles',
},
{
path: '/list/search/articles',
name: 'articles',
component: './List/Articles',
},
{
path: '/list/search/projects',
name: 'projects',
component: './List/Projects',
},
{
path: '/list/search/applications',
name: 'applications',
component: './List/Applications',
},
],
},
],
},
{
path: '/profile',
name: 'profile',
icon: 'profile',
routes: [
// profile
{
path: '/profile/basic',
name: 'basic',
component: './Profile/BasicProfile',
},
{
path: '/profile/advanced',
name: 'advanced',
authority: ['admin'],
component: './Profile/AdvancedProfile',
},
],
},
{
name: 'result',
icon: 'check-circle-o',
path: '/result',
routes: [
// result
{
path: '/result/success',
name: 'success',
component: './Result/Success',
},
{ path: '/result/fail', name: 'fail', component: './Result/Error' },
],
},
{
name: 'exception',
icon: 'warning',
path: '/exception',
routes: [
// exception
{
path: '/exception/403',
name: 'not-permission',
component: './Exception/403',
},
{
path: '/exception/404',
name: 'not-find',
component: './Exception/404',
},
{
path: '/exception/500',
name: 'server-error',
component: './Exception/500',
},
{
path: '/exception/trigger',
name: 'trigger',
hideInMenu: true,
component: './Exception/TriggerException',
},
],
},
{
name: 'account',
icon: 'user',
path: '/account',
routes: [
{
path: '/account/center',
name: 'center',
component: './Account/Center/Center',
routes: [
{
path: '/account/center',
redirect: '/account/center/articles',
},
{
path: '/account/center/articles',
component: './Account/Center/Articles',
},
{
path: '/account/center/applications',
component: './Account/Center/Applications',
},
{
path: '/account/center/projects',
component: './Account/Center/Projects',
},
],
},
{
path: '/account/settings',
name: 'settings',
component: './Account/Settings/Info',
routes: [
{
path: '/account/settings',
redirect: '/account/settings/base',
},
{
path: '/account/settings/base',
component: './Account/Settings/BaseView',
},
{
path: '/account/settings/security',
component: './Account/Settings/SecurityView',
},
{
path: '/account/settings/binding',
component: './Account/Settings/BindingView',
},
{
path: '/account/settings/notification',
component: './Account/Settings/NotificationView',
},
],
},
],
},
{
component: '404',
},
],
所以,可以得出结论,菜单是有路由的配置生成的。
接下来进行实验,新增一个路由

// new
{
path: '/new',
name: 'new',
icon: 'user',
routes: [
{
path: '/new/analysis',
name: 'analysis',
component: './Dashboard/Analysis',
},
{
path: '/new/monitor',
name: 'monitor',
component: './Dashboard/Monitor',
},
{
path: '/new/workplace',
name: 'workplace',
component: './Dashboard/Workplace',
},
],
},

可以看出,新的菜单以及添加到页面中,只是显示的文字不对。那么文字在哪里配置
呢?
其实,文字是在国际化文件中进行配置的:

'menu.new.analysis': 'New 分析页',
'menu.new.monitor': 'New 监控页',
'menu.new.workplace': 'New 工作台',

所有的页面依然是保存的src/pages中,在pages目录下,以功能为单元创建目录,如:
创建文件 NewAnalysis.js
import React from 'react';
class NewAnalysis extends React.Component {
render() {
return (
<div>NewAnalysis</div>
);
}
}
export default NewAnalysis;
修改路由中的路径:
{
path: '/new/analysis',
name: 'analysis',
component: './New/NewAnalysis',
},


可以看到,一个新的页面就创建好了,并且已经加入到菜单中。
在pro系统中,model是如何执行的,下面我们以表格为例,探究下在Pro中的执行流
程。

进入TableList.js代码进行查看:
生成表格的主要逻辑在这里:

在StandardTable中,使用table组件生成表格,其中数据源是data

TableList.js中,data数据从构造方法中获取到:

this.props中的rule数据,是通过@connect()修饰器获取:
需要注意的是:{ rule, loading }是解构表达式,从props中获取数据

数据从model中获取,在models下的rule.js中:

在TableList.js中,组件加载完成后进行加载数据:

在rule.js中,进行加载数据

queryRule是在/services/api中进行了定义:

数据的mock是在mock/rule.js中完成。

这就是整个数据的加载、更新流程
ant design入门
链接:https://pan.baidu.com/s/1gYnV5MCWHNleNNhP0_LvZA?pwd=a5b2
提取码:a5b2
复制这段内容后打开百度网盘手机App,操作更方便哦
ant design pro入门
链接:https://pan.baidu.com/s/1_wEpNo4AKtZw_QTMM-YGvw?pwd=ffkc
提取码:ffkc
–来自百度网盘超级会员V3的分享