react/antd notes
Ant Design Pro使用小记
背景
从Angular变更到React技术栈…
吾队, 统一使用React
了, 别问为什么, 我想了好几天也没搞明白.
写吧写吧.
如今, 就一个人好好搬砖吧.
本次项目直接使用antd pro
, 阿里的那一套……
初始化工作
由于本次直接使用的是
ali
的antd pro 中台解决方案. 基本相当于二次开发……
安装脚手架
1 | npm install dva-cli -g |
本地运行:
1 | cd projectName |
项目目录解析
1 | # 未包含隐藏.xx相关配置文件 |
mock
目录下都是mock数据用的文件public
目录下存放静态资源文件src
项目的源码tests
单元测试代码
关于以 .
开头的隐藏文件说明:
.roadhogrc.mock.js
该文件主要是用来在本地mock
数据时 拦截、代理本地接口请求用的. 具体使用, 后续会讲到..webpackrc.js
webpack打包配置相关设定, 可以看到已经将antd
这个库设置为打包进去了, 使用react
官方脚手架,创建时 时需要人为配置..eslint.js
,.babelrc.ks
都是相关配置文件, 暂不需要过度关注和修改.
src目录说明
1 | . |
assets
文件夹, 静态资源存放common
文件夹, 公共的, 按照ant pro设定就2个文件components
文件夹, 纯UI组件e2e
, end 2 end 测试models
文件夹, 存放模型Model(和数据操作密切相关的)文件, 和dva
密切关联.utils
, 一些常用函数工具类库services
, 存放一些接口请求相关的封装routes
文件夹, 存放页面相关的route component(不是纯UI组件, 其包含了一些具体的页面操作交互、方法定义、周期钩子函数componentDidMount
等).layouts
, 整个页面的布局设定polyfill.js
, 兼容性设置index.js
, 整个应用入口- 其它暂时不用管……
项目示例
需求: 需要展示一个 product
列表, 并在左侧导航栏的二级菜单下有一个入口.
menu配置
- 菜单配置, 添加入口, 修改
src/common/menu.js
文件.
找到path: 'management'
关键字, 在children
下按照同样的语法格式添加即可. 该语法和Angular
中的路由配置类似.
1 | path: 'management', |
路由配置
- 添加路由配置, 修改
src/common/router.js
文件. 在routerConfig
对象找个合适的位置按照同样的语法添加即可.
1 | '/management/product_line': { |
注意,
dynamicWrapper
方法的第二个数组参数, 通常用来设置该路由组件(即ProductLine)所对应的Model.
view层router component组件
- 添加该
View
层的路由组件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176<!-- 页面视图 -->
import React, { PureComponent, Fragment } from 'react';
import { connect } from 'dva';
import { Card, Button, Form, Table, Popconfirm, Divider, message } from 'antd';
import ProductLineModal from './ProductLineModal';
import PageHeaderLayout from '../../../layouts/PageHeaderLayout';
import styles from './ProductLine.less';
@connect(({ productline, loading }) => ({
productline,
loading: loading.effects['productline/fetch'],
}))
@Form.create()
export default class ProductLine extends PureComponent {
state = {
modalVisible: false,
mode: null,
currentRow: {},
};
componentDidMount() {
const { dispatch } = this.props;
dispatch({
type: 'productline/fetch',
});
}
handleModalVisible = (flag, row = {}, mode = 'create') => {
this.setState({
modalVisible: !!flag,
mode,
currentRow: row,
});
};
confirmDelete = fields => {
const { dispatch } = this.props;
dispatch({
type: 'productline/remove',
payload: {
deleteData: fields,
},
});
console.log('删除的内容: ');
console.log(fields);
message.success('删除成功');
this.setState({
modalVisible: false,
});
};
handleUpdate = fields => {
const { dispatch } = this.props;
dispatch({
type: 'productline/update',
payload: {
postData: fields,
},
});
console.log('更新的内容: ');
console.log(fields);
// console.log( fields.desc); // undefined
message.success('更新成功');
this.setState({
modalVisible: false,
});
};
handleAdd = fields => {
const { dispatch } = this.props;
dispatch({
type: 'productline/add',
payload: {
postData: fields,
},
});
console.log('新增的内容: ');
console.log(fields);
// console.log( fields.desc); // undefined
message.success('添加成功');
this.setState({
modalVisible: false,
});
};
render() {
const {
productline: {
list: { list: dataSource },
},
loading,
} = this.props;
const { modalVisible, mode, currentRow } = this.state;
const columns = [
{
title: '名称',
dataIndex: 'name',
align: 'center',
},
{
title: '所属 PA',
dataIndex: 'pa',
align: 'center',
},
{
title: '描述',
dataIndex: 'description',
align: 'center',
},
{
title: '操作',
align: 'center',
render: (text, record) => (
<Fragment>
<Button
type="primary"
icon="edit"
onClick={() => this.handleModalVisible(true, record, 'update')}
/>
编辑
<Divider type="vertical" />
<Popconfirm
title="确认删除?"
okText="确认"
cancelText="取消"
onConfirm={() => this.confirmDelete(record)}
>
<Button type="danger" icon="delete" />
删除
</Popconfirm>
</Fragment>
),
},
];
const parentMethods = {
handleAdd: this.handleAdd,
handleUpdate: this.handleUpdate,
handleModalVisible: this.handleModalVisible,
};
const parentData = {
modalVisible,
mode,
values: currentRow,
};
return (
<PageHeaderLayout title="产品线">
<Card bordered>
<div className={styles.tableList}>
<div className={styles.tableListOperator}>
<Button icon="plus" type="primary" onClick={() => this.handleModalVisible(true)}>
新建
</Button>
</div>
<Table
rowKey="id"
loading={loading}
dataSource={dataSource}
columns={columns}
bordered
/>
</div>
</Card>
<ProductLineModal {...parentMethods} {...parentData} />
</PageHeaderLayout>
);
}
}
模态框的简单封装:
1 | <!-- 上面👆那个页面用到的模态框封装 --> |
view层router component组件对应的model
- 通信
针对上述3中的route component
组件, 发现其中有几个方法以及与接口API
交互的方法.
第一个: 进入当前页面路由后, 初始化加载的数据. 在 ProductLine
类中可以看到:
1 | componentDidMount() { |
这是
React
提供的生命周期钩子函数,render
渲染到DOM
时就会自动触发该钩子函数, 从而发起请求fetch
; 具体写法:model的namespace/方法名
.
在类中调用该接口请求, 另一个必须的依赖就是 dva
(阿里基于redux + react-router + redux-saga 等库的轻量封装). 使用 connect
连接到该组件的 model
该组件的model如下:
1 | import { |
可以看到
view
层的router component
组件调用了其对用的model
里封装的方法. 但是实际的接口地址在哪里呢? 在下面👇
接口services层封装
在上面的第4步中可以看到该
model
从services
文件夹下的productline
中导入了几个方法.
接口 service
如下:
1 | import request from '../utils/request'; |
这里配置的URL 都是本地mock的, 默认是被本地mock接口拦截的.
至此, 整个数据流向和API请求使用, 按照上面的步骤 一步步下来 就很清晰了.
数据流
Ant Design Pro 内置使用的是
dva
.
对照此图即可 明了.
应用的数据流向(和API交互过程)
![](https://images.gitee.com/uploads/images/2018/0902/170752_1136de9e_1120068.png)
数据流向
Action:
Action是把数据从应用(如:用户输入、点击事件触发的数据、或是从接口请求获取的数据) 传递到store的一个载体。
Action本质上是JS 普通对象。约定:Action内必须有一个字符串类的type 字段,用来表示将要执行的动作。
一般/多数情况下,type会被定义成字符串常量;
Reducer:
指定 应用状态的变化如何响应actions并发送到store(actions只描述有事情发生这一事实,没有描述应用如何更新state);
Reducer是个纯函数,主要作用:接受旧的state和action,返回新的state。
Redux应用中, 所有的state都被保存在一个单一对象中。
所以,reducer函数中 只是单纯进行计算(返回新的state),没有API请求、没有变量修改、
Store:
Store就是把action和reducer联系到一起的对象。
React简单说明
React 并不是Web应用的完整解决方案, 只是DOM的抽象层.
React中值传递 都是向下传递的、单向的; 只能从父级 流向 子级.
组件声明规范: 无论是函数方式还是ES6中的class方式声明组件, 组件的命名规范: 首字母必须大写!
dva 说明
dva
是alibaba基于 redux
+ react-router
+ redux-saga
的一层轻量封装.
关于Redux
Redux和react没有 什么直接关系.
Redux不仅支持react, 也支持angular、ember、jQuery、纯JS.
关于Andt Pro
Ant Design of React 只是一个React相关的组件库。类似angular相关的UI库 ng-zorro. 而 Ant Design Pro相当于一个更上层的应用/模板,协助快速开发出应用。
相关资料
关于 dva
使用:
练习:
https://gitee.com/lomospace/dva-sample
React
Google即可.
Ant Design Pro
练习:
https://gitee.com/lomospace/antPro
Redux
Doc(中文)
https://cn.redux.js.org/
视频(英文)
https://egghead.io/lessons/
React 脚手架
官方:
https://github.com/facebook/create-react-app
dva系:
1 | # install |
https://dvajs.com/guide/getting-started.html#%E5%AE%89%E8%A3%85-dva-cli
版权声明:
本文由Lomo创作和发表,采用署名(BY)-非商业性使用(NC)-相同方式共享(SA)国际许可协议进行许可,
转载请注明作者及出处,本文作者为Lomo,本文标题为react/antd notes.