有一个需要实现的需求: 可展开表格 可以全部展开或关闭。如下:
技术实现前提: React + antd Table + Hooks + tsx
在 antd Table 上并没有找到这个属性,所以就自己上手来解决一下咯。
实现思路:
- 写一个同级的 div ,设置其css属性,让它绝对定位到 父表格对应的
th
上 - 设置其打开或关闭的显隐
- 使Table的所有
keys
可控 - 完善细节
总体实现:
// 展开行 可控
const [expKeys, setExpKeys] = React.useState(adata && adata.map(i => i.id));
// 数据源
const adata = [
{
id: 75,
name: "一个name",
aValue: "处理中",
exList: [
{
bValue: "zz",
id: 241,
},
{
bValue: "alsldsad",
id: 242,
},
{
bValue: "qwqeqee",
id: 243,
}
]
},
{
id: 76,
name: "另一个name",
aValue: "已完成",
exList: [
{
bValue: "sasa",
id: 1241,
},
{
bValue: "plplpl",
id: 1242,
},
{
bValue: "asasasssssss",
id: 1243,
}
]
}
];
// 全部关闭或打开
/**
* type boolean值
* true 表示 关闭所有
* false 表示 展开所有
**/
const openOrCloseAll = (type: boolean) => {
type ? setExpKeys([]) : setExpKeys(adata && adata.map(i => i.id));
};
// 子表格渲染
const expandedRowRender = record => {
const columns: ColumnProps<any>[] = [
{
title: '子名称',
dataIndex: 'bValue',
width: 160,
render: text => (
<div style={{ width: 140 }}>
<Ellipsis lines={1} tooltip>
{text}
</Ellipsis>
</div>
),
},
];
return (
<Table
columns={columns}
size="small"
dataSource={record.exList || []}
pagination={false}
rowKey={record => record.id}
/>
);
};
// render
/**
* 样式来自 antd Table的展开和关闭,这样就和下面子表格样式一样了
**/
<div style={{ position: 'relative' }}>
<div style={{ position: 'absolute', left: 30, top: 8, zIndex: 1 }}>
<div
onClick={() => openOrCloseAll(true)}
style={{ display: expKeys.length ? 'inline-block' : 'none' }}
className="ant-table-row-expand-icon ant-table-row-expanded"
/>
<div
onClick={() => openOrCloseAll(false)}
style={{ display: expKeys.length ? 'none' : 'inline-block' }}
className="ant-table-row-expand-icon ant-table-row-collapsed"
/>
</div>
<Table
dataSource={adata}
size="small"
// 可控的展开与关闭数组
expandedRowKeys={expKeys}
// 单个展开或关闭,操作数组
onExpand={(b, r) => {
const newExp: any = b ? [...expKeys, r.id] : expKeys.filter(i => i !== r.id);
setExpKeys(newExp);
}}
expandedRowRender={record => expandedRowRender(record)}
pagination={false}
columns={columns}
rowKey={record => record.id}
scroll={{ x: true }}
/>
</div>
实现后如图: