Table 表格 的合并单元格、隔行变色的技巧、其它一些用过的 API 的例子
前言:基础的用法就不强调了,这里一笔带过。接下来直接看代码。注意:关键代码用红色粗体字体
第一个例子:合并单元格
在这个例子里,根据antd官网介绍,可以看到这样一句话:表头只支持列合并,使用 column 里的 colSpan 进行设置。表格支持行/列合并,使用 render 里的单元格属性 colSpan 或者 rowSpan 设值为 0 时,设置的表格不会渲染。转换一下,让我们一开始就在数据中埋下一个 span 属性,方便后续操作。
import React, { useState, useEffect,useCallback } from 'react';
import './index.less';
import { Modal, Table } from 'antd';
import moment from 'moment';
import { config_discount_list } from '../../../services/api';
function DiscountsDetailModal(props) {
const [tableData, setTableData] = useState([]); // list数据
const [visible,setVisible ] = useState(false);
const [tableColumns,setTableColumns] = useState([]);
const [filterParams, setFilterParams] = useState({}); // 查询表单的参数
// const [updateList, setUpdateList] = useState([]); // 回显
const [serveConfigId, setServeConfigId] = useState(); // 是否修改状态
// const format = 'HH:mm';
// const dateFormat = 'YYYY/MM/DD';
// 后端返回的数据
// [
// {
// dateDiscount: 1,
// endDate: "2019-01-02",
// startDate: "2019-01-01",
// timeData:[
// {
// discountPrice: 1,
// endTime: "21:21:21",
// startTime: "20:20:20",
// timeDiscount: 1,
// },
// {
// discountPrice: 2,
// endTime: "21:21:21",
// startTime: "20:20:20",
// timeDiscount: 2,
// },
// {
// discountPrice: 3,
// endTime: "21:21:21",
// startTime: "20:20:20",
// timeDiscount: 3,
// }
// ]
// },
// {
// dateDiscount: 1,
// endDate: "1111-11-11",
// startDate: "1111-11-11",
// timeData:[
// {
// discountPrice: 0.012,
// endTime: "00:00:00",
// startTime: "00:00:00",
// timeDiscount: 2,
// },
// {
// discountPrice: 0.013,
// endTime: "00:00:00",
// startTime: "00:00:00",
// timeDiscount: 3,
// }
// ]
// }
// ]
// 我操作以后得出的数据
// [
// {
// key:0,
// date:'1111',
// dateDiscount:'0.1',
// createTime:'1111-22222',
// timeDiscount:'0.222',
// discountPrice:'1111',
// span:2, // :0 代表不占行 :1 代表占一行,:2 代表占两行,以此类推,
// 当这里占了两行,下一行一定要为空行,即 span:0
// 同理这里是 :3 的话,下面必须连续出现两个 span:0
// },
// {
// key:1,
// date:'222',
// dateDiscount:'0.1',
// createTime:'55555-66666',
// timeDiscount:'0.3333',
// discountPrice:'2222',
// span:0,
// },
// {
// key:2,
// date:'3333',
// dateDiscount:'0.1',
// createTime:'77777-88888',
// timeDiscount:'0.4444',
// discountPrice:'3333',
// span:4,
// },
// {
// key:3,
// date:'444444',
// dateDiscount:'0.1',
// createTime:'77777-88888',
// timeDiscount:'0.4444',
// discountPrice:'3333',
// span:0,
// },
// {
// key:4,
// date:'55555',
// dateDiscount:'0.1',
// createTime:'77777-88888',
// timeDiscount:'0.4444',
// discountPrice:'3333',
// span:0,
// },
// {
// key:5,
// date:'66666',
// dateDiscount:'0.1',
// createTime:'77777-88888',
// timeDiscount:'0.4444',
// discountPrice:'3333',
// span:0,
// }
// ]
const requestList = useCallback(async () => {
let res = await config_discount_list({ serveConfigId});
if (res.data.responseCode) return
let responseData = res.data.responseData;
setVisible(true)
let arr = [];
responseData.map(responseDataItem=>{
const len = responseDataItem.timeData.length;
responseDataItem.timeData.map((timeDataItem,index)=>{
arr = [
...arr,
{
time:timeDataItem.startTime+'-'+timeDataItem.endTime,
discountPrice: timeDataItem.discountPrice,
timeDiscount: timeDataItem.timeDiscount,
date:responseDataItem.startDate === '1111-11-11' ? '其他日期' : responseDataItem.startDate+'-'+responseDataItem.endDate,
dateDiscount:responseDataItem.dateDiscount,
span:index === 0 ? len : 0
}
]
return arr
})
return arr
})
const tableData = arr.map((item, index) => {
item.key = index;
return item;
})
setTableData(tableData);
})
useEffect(()=>{
setVisible(props.visible);
setServeConfigId(props.serveConfigId);
}, [props.visible, props.serveConfigId])
useEffect(()=>{
if(serveConfigId && serveConfigId !== -1){
requestList()
}
}, [serveConfigId])
useEffect(()=>{
setTableColumns([
{
title: '日期',
dataIndex: 'date',
key: 'date',
width: 140,
render: (value, row, index) => { // 需要被合并的单元格,只需要这样设置就行了。比官网的简单,但是,一开始要处理好数据中的 span 属性。
return {// 这里可以返回标签,比如:return <span title={value}>{value}</span>
children: value,
props: {rowSpan:row.span},
};
},
},
{
title: '日期折扣',
dataIndex: 'dateDiscount',
key: 'dateDiscount',
width: 140,
render: (value, row) => {
return {
children: value,
props: {rowSpan:row.span},
};
},
},
{
title: '时间',
dataIndex: 'createTime',
key: 'createTime',
width: 140
},
{
title: '时间折扣',
dataIndex: 'timeDiscount',
key: 'timeDiscount',
width: 140
},
{
title: '价格(元)',
dataIndex: 'discountPrice',
key: 'discountPrice',
width: 140
}
])
}, [])
const onCancel = () => {
setVisible(false)
props.close(false)
}
return (
<Modal
destroyOnClose={true}
className="discountsDetailModal"
title="优惠详情"
centered
visible={ visible }
onCancel={ onCancel }
okText="确定"
cancelText="取消"
maskClosable={ false }
width={600}
>
<Table columns={tableColumns} dataSource={tableData} bordered />
</Modal>
)
}
export default DiscountsDetailModal;
到此为止,我们完成了表格的合并列,新的问题是如果需要隔行变色显示,这是可以发现隔行变色并不是我们想要的样式。
下面有请第二个例子:隔行变色
rowClassName这一api,通过判断index的奇偶来实现不同的样式分配。 rowClassName是一个函数,它的第一个参数是record,对应的是这一行的所有数据,第二个参数是index,对应的是table组件自己计数的第几行;
没有合并单元格的简单情况:
直接判断index的奇偶作出不同的样式分配;然后根据不同的 className 进行隔行变色的 css 修改
rowClassName={(record, index) => {
let className = 'odd';
if (index % 2 === 1) className = 'even';
return className;
}}
合并单元格后的复杂情况:
如果依靠rowClassName中自带的index是不行的,所以这时候需要自己设定一个fakeIndex和一个用来指示此行是否被合并的标志(我设的是一个标志从此行起还有多少合并行的计数count,遇到普通行,fakeIndex加1;如果遇到被合并的行,则fakeIndex不加1,count减1。这里可以这么做的原因是antd的表格在渲染的时候是每渲染一行,就执行一次rowClassName的函数。
具体实现代码如下:
首先在React Component的constructor里面申明fakeIndex和count
constructor() { super(); this.fakeIndex = 0; this.licensesCount = 1; }
然后在render渲染的<Table/>里面设置rowClassName函数
<Table columns={tableColumns} dataSource={tableData} bordered // 是否展示外边框和列边框 className="reset-ant-table" pagination={false} // 分页器,参考配置项或 pagination 文档,设为 false 时不展示和进行分页 scroll={{y: 300}} //表格是否可滚动,配置项 rowClassName = { record => { let className = 'reset-ant-table odd'; if (record.span > 1) { this.licensesCount = record.span; // 用来初始化合并的行数 } if (record.span !== 0) { className = "reset-ant-table odd oddHover"; if (this.fakeIndex % 2 === 1) { className = 'reset-ant-table even evenHover'; } } else { if (this.fakeIndex % 2 === 1) { className = 'reset-ant-table even'; } } if (record.span === 0) { this.licensesCount-- if (this.licensesCount === 1) { this.fakeIndex++ } } if (record.span === 1) { this.fakeIndex++ } return className; } } ></Table>
className 中的 odd 和 even 可以设置隔行变色,oddHover 和 evenHover 可以设置鼠标移上时的样式,虽然不能说完美,单至少是一种解决方案。
那么顺便把 less 也加上,可供参考:
.reset-ant-table{ .ant-table-tbody{ tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td { background-color: #DFE8FF; } .oddHover:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td:first-child{ background-color: #FFFFFF; } .evenHover:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td:first-child{ background-color: #F0F4FD; } .odd{ background-color: #FFFFFF; } .even{ background-color: #F0F4FD; } } }
其它一些用过的 API 的例子
当你在官网查找 api ,却还是不明白如何使用,这里让你剪切复制就好,ps:有栗子就是好
1. 默认文案设置
2. 表格行 key 的取值,可以是字符串或一个函数
<Table rowKay={(recode, index) => `${recode.id}${index}`} ></Table>
3. onRow 的用法
没错,就是官网上抄的,此例子适用于 onRow、onHeaderRow、onCell、onHeaderCell
<Table onRow={record => { return { onClick: event => {}, // 点击行 onDoubleClick: (event, val) => {}, // 如果第一个参数不能满足你,可以看看第二个 onContextMenu: event => {}, onMouseEnter: event => {}, onMouseLeave: event => {}, }; }} onHeaderRow={column => { return { onClick: () => {}, // 点击表头行 }; }} />

浙公网安备 33010602011771号