有一個需要實現的需求: 可展開表格 可以全部展開或關閉。如下:
技術實現前提: 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>
實現後如圖: