前言:基础的用法就不强调了,这里一笔带过。接下来直接看代码。注意:关键代码用红色粗体字体
第一个例子:合并单元格
在这个例子里,根据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 { 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 可以设置鼠标移上时的样式,虽然不能说完美,单至少是一种解决方案。