前言:基础的用法就不强调了,这里一笔带过。接下来直接看代码。注意:关键代码用红色粗体字体
第一个例子:合并单元格
在这个例子里,根据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', 140, render: (value, row, index) => { // 需要被合并的单元格,只需要这样设置就行了。比官网的简单,但是,一开始要处理好数据中的 span 属性。 return {// 这里可以返回标签,比如:return <span title={value}>{value}</span> children: value, props: {rowSpan:row.span}, }; }, }, { title: '日期折扣', dataIndex: 'dateDiscount', key: 'dateDiscount', 140, render: (value, row) => { return { children: value, props: {rowSpan:row.span}, }; }, }, { title: '时间', dataIndex: 'createTime', key: 'createTime', 140 }, { title: '时间折扣', dataIndex: 'timeDiscount', key: 'timeDiscount', 140 }, { title: '价格(元)', dataIndex: 'discountPrice', key: 'discountPrice', 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: () => {}, // 点击表头行 }; }} />