React+antd:为表格添加成组标记
最近在做前端开发的时候遇到一个需求:对后端传回的数据中满足条件的相邻行用符号连接起来,表示关联关系。我是个前端新人,因项目需要接手前端开发工作,为了实现这个需求颇费了一番功夫。现在记录下来方便后来者。
这篇文章首先用原生CSS实现了这个需求,然后在React工程中的antd表格组件中实际应用。
用CSS实现表格的成组标记
本文以在相同国家的人名前加上成组标记为例
效果如下图所示
<style>
table {
width: 800px;
margin: 20px auto;
}
table td,
table th {
border-bottom: 1px solid #E5E5E5;
padding: 10px 6px;
}
.grp {
position: relative;
}
.grp::before {
position: absolute;
content: '';
width: 8px;
height: 50%;
left: -10px;
border-left: 2px solid #A2A0A0;
}
.top::before {
border-top: 2px solid #A2A0A0;
top: 50%;
}
.bottom::before {
border-bottom: 2px solid #A2A0A0;
bottom: 50%;
}
.center::before {
height: 100%;
top: 0;
}
</style>
<table cellspacing="0px">
<thead>
<tr>
<th>name</th>
<th>age</th>
<th>country</th>
</tr>
</thead>
<tbody>
<tr>
<td class='grp top'>张一</td>
<td>12</td>
<td>China</td>
</tr>
<tr>
<td class='grp bottom'>张二</td>
<td>12</td>
<td>China</td>
</tr>
<tr>
<td>山本</td>
<td>12</td>
<td>Japan</td>
</tr>
<tr>
<td class='grp top'>张三</td>
<td>12</td>
<td>France</td>
</tr>
<tr>
<td class='grp center'>张四</td>
<td>12</td>
<td>France</td>
</tr>
<tr>
<td class='grp bottom'>张五</td>
<td>12</td>
<td>France</td>
</tr>
</tbody>
</table>
在React+antd中实现表格的成组标记
在antd的表格组件中没有办法对指定行的指定td添加指定类名,通过查阅官方文档发现可以通过组件的rowClassName
和columns.className
实现我们的需求
rowClassName
通过函数设置指定行的类名columns.className
指定表格某一列的类名,只能接受字符串类名
主要分为两个步骤
- 对表格的数据
data
进行解析,对每一条数据的前后行比对contry
字段,计算出在成组标记中的位置并记录在对象flagObj
中 - 编写
rowClassName
函数,对每一行指定相应的类名
js
const {
Table,
Divider,
Tag
} = antd;
const data = [{
id: 1,
name: 'zhangsan',
age: 42,
contry: 'China'
}, {
id: 2,
name: 'lisi',
age: 42,
contry: 'China'
}, {
id: 3,
name: 'shanben',
age: 42,
contry: 'Japan'
}, {
id: 4,
name: 'John Brown',
age: 32,
contry: 'France'
}, {
id: 5,
name: 'Jim Green',
age: 42,
contry: 'France'
}, {
id: 6,
name: 'Joe Black',
age: 32,
contry: 'France'
}];
let flagObj = {}
const doFlag = (items) => {
items.forEach((e, i) => {
const contryName = e.contry ? e.contry : 'none'
let preflag = false, nextflag = false
if (items[i - 1] && items[i - 1].contry === contryName) {
preflag = true
}
if (items[i + 1] && items[i + 1].contry === contryName) {
nextflag = true
}
if (preflag && nextflag) {
flagObj[e.id] = 'center flag'
} else if (preflag && !nextflag) {
flagObj[e.id] = 'bottom flag'
} else if (!preflag && nextflag) {
flagObj[e.id] = 'top flag'
}else{
flagObj[e.id] = ' noflag'
}
})
}
data && doFlag(data)
const columns = [{
title: 'Name',
dataIndex: 'name',
key: 'name',
className: 'grp', //
}, {
title: 'Age',
dataIndex: 'age',
key: 'age'
},
{
title: 'Contry',
dataIndex: 'contry',
key: 'contry'
}];
//成组标记
const handleRowClassName = (record, index) => {
return record && flagObj[(record.id)] && (flagObj[(record.id)])
}
ReactDOM.render(
< Table
columns={columns}
dataSource={data}
pagination={false}
rowClassName={handleRowClassName}
/>, mountNode);
less
.flag {
.grp {
position: relative;
&::before {
position: absolute;
content: '';
width: 8px;
height: 55%;
left: -10px;
border-left: 2px solid;
border-color: #A2A0A0;
}
}
}
.top .grp::before {
border-top: 2px solid;
top: 50%;
}
.bottom .grp::before {
border-bottom: 2px solid;
bottom: 50%;
}
.center .grp::before {
height: 100%;
top: 0;
}