做为React技术栈的坚决拥护者,必定离不开阿里爸爸的大怀抱。做为国内最好用的组件库【之一】的Ant Design迎来个跨版本大更新,年后复工后我在第一时间便进行了尝鲜,恰好公司有老项目重构,在初步了解以后,决定尝试在新项目中使用And Design 4.0进行开发,与之对应的Ant Design Pro也更新到了4.0版本,Ant Design Pro是给予Ant Design的开箱即用中台前端/设计解决方案。简单的说,Ant Dsign是砖头,那Ant Design Pro就是用这些砖头垒起来的框架,你能够基于这个框架来按照你本身的想法从新装修,也能够在不破坏主体结构的状况下拆除部份内容重建。举个例子,对于我来讲,原框架集成的国际化部分是无用的,那我就须要剔除。本系列文章主要针对在项目中使用Ant Design 4.0中遇到的一下值得注意的点~html
本片先来讲一下让我非常喜欢的ProTable这个新组件,让咱们一块儿来看看它到底Pro在哪里。前端
以往,咱们在作列表功能之类,须要重复的去手动的在componentDidMount钩子写请求数据,而后把数据重model中取出来,而后再放到Table组件的dataSource属性中,而后还要处理pageChange事件,而后还要手动的去渲染搜索项,而后就又得本身去引入各类组件,而后又各类堆接节点...这个过程下来,人都要惆怅咯。再加之通常作这种中后台管理系统,相似的功能不少,重复且低效的工做方式简直没法忍受。react
import React, { PureComponent, Fragment } from 'react';
import { connect } from 'dva';
import { Row, Col, Card, Form, Input, Button, DatePicker, Divider, message, Table } from 'antd';
import router from 'umi/router';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import { formatDate, getStartTimeStamp, getEndTimeStamp } from '@/utils/utils';
import styles from './style.less';
const FormItem = Form.Item;
const { RangePicker } = DatePicker;
const getValue = obj =>
Object.keys(obj)
.map(key => obj[key])
.join(',');
/* eslint react/no-multi-comp:0 */
@connect(({ approval, studentManagment, loading }) => ({
approval,
studentManagment,
loading: loading.effects['studentManagment/fetch'],
}))
@Form.create()
class StudentManagement extends PureComponent {
state = {
selectedRows: [],
formValues: {},
};
columns = [
{
title: '名称',
dataIndex: 'name',
render: val => val || '-',
},
{
title: '建立日期',
dataIndex: 'createTime',
render: val => val && formatDate(val),
}, {
title: '性别',
dataIndex: 'sex'
},
{
title: '年龄',
dataIndex: 'age'
},
{
title: '学校',
dataIndex: 'school'
},
{
title: '年级',
dataIndex: 'grade'
},
{
title: '操做',
render: (text, record) => (
<Fragment> <a onClick={() => router.push({ pathname: '/common/landing-page-management/edit', query: { id: record.id, }, }) } > 编辑 </a> <Divider type="vertical" /> <a onClick={() => this.onCopyLink(record)}>复制连接</a> </Fragment>
),
},
];
componentWillMount() {
this.getData();
}
getData = params => {
const { dispatch } = this.props;
dispatch({
type: 'studentManagment/fetch',
payload: params,
});
};
onCopyLink = record => {
const input = document.createElement('input');
input.value = record.shortUrl;
document.body.appendChild(input);
input.select();
input.setSelectionRange(0, input.value.length);
document.execCommand('Copy');
document.body.removeChild(input);
message.success('复制成功!');
};
handleStandardTableChange = (pagination, filtersArg, sorter) => {
const { formValues } = this.state;
const filters = Object.keys(filtersArg).reduce((obj, key) => {
const newObj = { ...obj };
newObj[key] = getValue(filtersArg[key]);
return newObj;
}, {});
const params = {
page: pagination.current,
pageSize: pagination.pageSize,
...formValues,
...filters,
};
if (sorter.field) {
params.sorter = `${sorter.field}_${sorter.order}`;
}
this.getData(params);
};
handleFormReset = () => {
const { form } = this.props;
form.resetFields();
this.setState({
formValues: {},
});
this.getData();
};
handleSelectRows = rows => {
this.setState({
selectedRows: rows,
});
};
handleSearch = e => {
e.preventDefault();
const { form } = this.props;
form.validateFields((err, fieldsValue) => {
if (err) return;
const values = {
name: fieldsValue.name,
startDate: fieldsValue.date && getStartTimeStamp(fieldsValue.date[0]),
endDate: fieldsValue.date && getEndTimeStamp(fieldsValue.date[1]),
};
this.setState({
formValues: values,
});
this.getData(values);
});
};
renderForm() {
const {
form: { getFieldDecorator },
} = this.props;
return (
<Form onSubmit={this.handleSearch} layout="inline"> <Row gutter={{ md: 8, lg: 24, xl: 48 }}> <Col md={8} sm={24}> <FormItem label="名称"> {getFieldDecorator('name')(<Input placeholder="请输入" />)} </FormItem> </Col> <Col md={8} sm={24}> <FormItem label="建立日期"> {getFieldDecorator('date')(<RangePicker style={{ width: '100%' }} />)} </FormItem> </Col> <Col md={8} sm={24}> <Button type="primary" htmlType="submit"> 查询 </Button> <Button style={{ marginLeft: 8 }} onClick={this.handleFormReset}> 重置 </Button> </Col> </Row> <div style={{ overflow: 'hidden' }}> <div style={{ float: 'left', marginBottom: 24 }}> <Button icon="plus" type="primary" onClick={() => router.push({ pathname: '/common/landing-page-management/add' })} > 新增 </Button> </div> </div> </Form>
);
}
render() {
const {
studentManagment: { list },
loading,
} = this.props;
const { selectedRows } = this.state;
return (
<PageHeaderWrapper> <Card bordered={false}> <div className={styles.tableList}> <div className={styles.tableListForm}>{this.renderForm()}</div> <Table selectedRows={selectedRows} loading={loading} data={list} columns={this.columns} onSelectRow={this.handleSelectRows} onChange={this.handleStandardTableChange} /> </div> </Card> </PageHeaderWrapper>
);
}
}
export default StudentManagement;
复制代码
上面是一个用Table来作查询列表功能的一个小demo,大体流程以下:markdown
能够发现这实际上是一个重复的工做,大部分状况下只须要按照固定熟悉来写差很少同样的代码就行了。antd
如今,咱们有了ProTable,再来看看怎么作呢~app
import { PlusOutlined } from '@ant-design/icons';
import { Button, Divider } from 'antd';
import React, { Component, Fragment } from 'react';
import router from 'umi/router';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import ProTable from '@ant-design/pro-table';
import { copyString, formatDate, getStartTimeStamp, getEndTimeStamp } from '@/utils/utils';
import { connect } from 'dva';
import { queryRule } from './service';
class StudentManagement extends Component {
columns = [
{
title: '名称',
dataIndex: 'name',
ellipsis: true,
},
{
title: '建立日期',
dataIndex: 'createTime',
valueType: 'dateRange',
render: val => val && formatDate(val),
},
{
title: '性别',
dataIndex: 'sex',
hideInSearch: true,
},
{
title: '年龄',
dataIndex: 'age',
hideInSearch: true,
},
{
title: '学校',
dataIndex: 'school',
hideInSearch: true,
},
{
title: '年级',
dataIndex: 'grade',
hideInSearch: true,
},
{
title: '操做',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => (
<Fragment> <a onClick={() => router.push({ pathname: '/public-resource/landing-page-management/edit', query: { id: record.id, }, }) } > 编辑 </a> <Divider type="vertical" /> <a onClick={() => copyString(record.shortUrl)}>复制连接</a> </Fragment>
),
},
];
render() {
return (
<PageHeaderWrapper> <ProTable toolBarRender={() => [ <Button type="primary" onClick={() => router.push('/public-resource/landing-page-management/add')} > <PlusOutlined /> 新建 </Button>, ]} rowKey="id" dateFormatter="number" request={params => queryRule({ ...params, current: undefined, startDate: params.createTime && getStartTimeStamp(params.createTime[0]), endDate: params.createTime && getEndTimeStamp(params.createTime[1]), }) } columns={this.columns} /> </PageHeaderWrapper>
);
}
}
export default connect(({ studentManagement }) => ({
studentManagement,
}))(StudentManagement);
复制代码
写完以后最直观的感觉就是代码量足足少了一半!!ProTable将请求数据、处理数据、渲染节点的这个过程封装了起来,使得咱们只须要按照他的约定来进行配置便可完成大部分操做。如今:咱们流程就变成了:框架
在新的ProTable中,与以往不一样的是,咱们须要维护的columns中新增了一个valueType属性,按照约定值,ProTable将根据这个属性来渲染表单项和表头。剩下的Search事件、Reset事件、pageChange事件等等等等...ProTable都会帮你作好。less
ProTable大法好,上车保平安。学会用ProTable,今后列表一把梭~ide
官方文档地址:protable.ant.design/oop
文章写得比较简略,有问题欢迎在评论区留言~