最近项目需求:在表格底部添加一行为金额的合计行,然后分页每页都显示,金额字段是后端返回的数据,前端不进行计算。
因为项目的UI框架使用的是Ant Design 3.x
版本,找了一下Table的使用方法,发现居然没有合计数据这样一个功能,但是提供了一个footer属性用来做Table底部的空间显示。然后我使用footer中添加一个Table来做了一下合计行显示,勉强能做出来,但是需要修改Table的css样式,并且在不同分辨率下表格的线框无法对齐,总之就是很low。
多方查找资料,以及自己的不断试错,终于找到了一种颇为完美的解决方法:将合计行追加到table表格内部,修改分页功能,维护也更加方便。
先上图,切换分页后table底部也有合计行:
上代码:
import React, { PureComponent } from 'react';
import { Table } from 'antd';
import { formatMoney } from '@/utils/utils'; //自定义格式化金额方法
// columns中的多余字段删除掉了,都是重复的样式,这里为了减少代码量。
const columns = [
{
title: '序号',
width: 66,
dataIndex: 'totalIndex',
render: (text, record, index) => {
if (record.totalIndex == '合计') {
return text;
} else {
return ++index; //++index相当于index+1
}
}
},
{
title: '凭证号',
width: 200,
dataIndex: 'voucherCode',
render: (text, record) => {
//因为只有合计行追加了字段totalIndex,所以判断当前字段来让合计行的凭证号列数据为空,只计算金额列。
//产品说让空白显示!!!
if (record.totalIndex) {
return '';
} else {
return text || '--';
}
}
},
{
title: '借方金额',
dataIndex: 'debit',
render: text => formatMoney(text)
},
{
title: '贷方金额',
dataIndex: 'credit',
render: text => formatMoney(text)
}
];
export default class ListTable extends PureComponent {
// 切换分页时调用函数
changePagination = pagination => {
const {
dispatch,
queryFinanceList: { formValues }
} = this.props;
const params = {
page: pagination.current, //当前分页的页码
limit: pagination.pageSize - 1, //这里必须要减1,因为与后台规定每页获取的数据为10,此处的pageSize为11。
queryCondition: { ...formValues },
};
dispatch({
type: 'queryFinanceList/fetch',
payload: params,
});
};
render() {
const {
loading,
queryFinanceList: {
list,
pageNum,
total: computedTotal, //重命名为computedTotal
pages,
pageSize
},
} = this.props;
//定义合计行数据
const totalRow = {
id: String(Math.random()),
totalIndex: '合计',
debit: 1165000, //应当取从后台返回数据,此处为演示,所以自定义了默认值
credit: 1183000, //应当取从后台返回数据,此处为演示,所以自定义了默认值
}
//将合计行数据添加到list数组中后生成新数组:_list,此时table每页的数据为11
const _list = list && list.length > 0 ? [...list, totalRow] : [];
//table与pagination组件之间的联动
//因为table表格每页显示的数据被pagenation分页默认的每页显示数pageSize所限制,默认为10,为了让合计行显示到页面上,需+1。
const _pageSize = pageSize + 1;
//table表格需要获取的总数据,为了让table将后台获取数据和新增合计行数据全部显示出来,需重新计算总数。
const _total = computedTotal + pages;
//分页设置
const paginationDefault = {
showSizeChanger: true,
showQuickJumper: true,
current: pageNum,
total: _total,
pageSize: _pageSize,
//因为与后台规定每页获取的数据为10,而前端自定义追加了一条合计行,这导致当前table的每页数据为11条,所以需要手动将分页数据+1
//若是想显示为['10', '20', '30', '40'],则修改每页获取数据为9即可。
pageSizeOptions: ['11', '21', '31', '41'],
//此处显示的是从后台获取的总数据数,合计行不在其中。
showTotal: () => `共${computedTotal}条记录`
}
return (
<Table
loading={loading}
rowKey={'id'}
scroll={{ x: true }}
bordered={true}
loading={loading}
columns={columns}
dataSource={_list}
pagination={paginationDefault}
onChange={this.changePagination}
/>
);
}
}
如果使用过ant design的Table组件以及Pagination组件的话,上面基本没有什么难点。
逻辑理解的话有两个难点:
1、分页功能的total和pageSize的计算方式?
2、合计行totalRow与后台返回数据的关系?
在table表格中使用pagination分页功能后,table每页显示的数据被pagination的pageSize(每页显示数据)限制,如果pageSize为10的话,那table中每页就只能显示10条数据。现在我们手动给table添加了合计行totalRow,那table每页的数据显示就变为了11,这时候pageSize若还是10,那第11条数据是显示不出来的,所以pageSize需要修改为11,这样合计行totalRow就能显示出来了。我们在切换分页的时候,是需要请求后台数据的,pageSize需要当做请求参数传送给后台。但是这时候我们设定了pageSize为11,而规定的每页显示的真实数据为10,所以需要在请求数据时pageSize-1。
total也需要跟随pageSize的+1而改变。如果后台返回的total为61,pageSize为10,pages(几个页面)为7,那么“新total”的计算方式为:61+1*7=68。因为在table每页中都添加了一条合计行totalRow的数据,所以计算方式为61+1*7=68。如果手动添加了两条数据,那么总数计算就应当为:61+2*7=75。
若还有更优美的实现方式,欢迎留言分享。
参考:react:antd 中 table 添加合计行