table表格支持這種樹形可展開的形式,只需要在tableData中有children數據
不過這種用法是一開始獲取表格數據時,就把children數據拿到了
實際場景中可能需要點擊展開按鈕時再去調取children數據
可以有兩種方法實現這個需求
第一種: 通過expandable的onExpand方法,點擊展開時獲取數據,再通過篩選過濾,將數據添加到父級數據的children中
這里使用的是protable,antd table組件用法也是一樣的.不過因為是通過改變tableData的數據,所以不要用request的方法賦值tableData
數據要求: 父級數據中需要一個字段表示當前的層級, 如果不是頂層數據,還要有一個字段表示父級id,方便添加數據時匹配
這里層級最多三級, 直接寫了,如果不確定有幾層的,需要寫遞歸
import React, { useState, useEffect } from 'react';
import ProTable from '@ant-design/pro-table';
import { getCityList, getAreaList, getProvinces } from '@/services/citylist';
import { isEmpty } from 'lodash';
const TreeTable: React.FC = () => {
const [tableData2, setTableData2] = useState<any[]>([]);
const colums: any[] = [
{
title: '省份',
dataIndex: 'province',
width: '20%',
render: (val: string, recored: any) => {
if (recored.city) return '-';
return val;
},
},
{
title: '市區',
dataIndex: 'city',
width: '20%',
render: (val: string, recored: any) => {
if (recored.area) return '-';
return val;
},
},
{
title: '區縣',
width: '20%',
dataIndex: 'area',
},
{
title: 'GDP(億)',
width: '19%',
dataIndex: 'gdp',
valueType: 'digit',
},
{
title: '排名',
width: '18%',
dataIndex: 'rank',
},
];
// 獲取樹形數據
const getData2 = async () => {
const res: any = await getProvinces();
setTableData2(res);
};
useEffect(() => {
getData2();
}, []);
// 點擊展開
const areaExpandedRowsChange = async (expanded: boolean, record: any) => {
console.log(expanded, record);
// 做一下限制,如果已經有數據,不再重復請求數據
if (expanded && record.children && isEmpty(record.children)) {
if (record.level === 1) { // 獲取第一級數據的children
const res = await getCityList(record.province, 1);
setTableData2(
tableData2.map((item: any) => {
if (item.id === record.id) {
return {
...item,
children: res,
};
}
return item;
}),
);
} else if (record.level === 2) { // 獲取第二級數據的children
const res = await getAreaList(record);
setTableData2(
tableData2.map((item: any) => {
const obj = {
...item,
};
if (item.id === record.parentId) {
item.children.forEach((ss: any) => {
if (ss.id === record.id) {
ss.children = res;
}
});
}
return obj;
}),
);
}
}
};
return (
<ProTable
bordered
columns={colums}
rowKey="id"
search={false}
dataSource={tableData2}
expandable={{
onExpand: areaExpandedRowsChange,
}}
pagination={false}
toolBarRender={false}
/>
)
}
export default TreeTable;
這種方法在添加數據時,麻煩一點,但是展示和交互比較友好.適合層級確定,並且層級數比較少的情況
第二種方法: 通過expandable的expandedRowRender屬性,返回自定義內容
這種可以方便的定義要展示的children數據,因為返回的是DOM,
這種層級可以嵌套,但是有幾層數據必須確定
import React, { useState, useEffect } from 'react';
import ProTable from '@ant-design/pro-table';
import { getCityList, getAreaList, getProvinces } from '@/services/citylist';
import { isEmpty } from 'lodash';
const TreeTable: React.FC = () => {
const [tableData2, setTableData2] = useState<any[]>([]);
const colums: any[] = [
{
title: '省份',
dataIndex: 'province',
width: '20%',
render: (val: string, recored: any) => {
if (recored.city) return '-';
return val;
},
},
{
title: '市區',
dataIndex: 'city',
width: '20%',
render: (val: string, recored: any) => {
if (recored.area) return '-';
return val;
},
},
{
title: '區縣',
width: '20%',
dataIndex: 'area',
},
{
title: 'GDP(億)',
width: '19%',
dataIndex: 'gdp',
valueType: 'digit',
},
{
title: '排名',
width: '18%',
dataIndex: 'rank',
},
];
const colums2 = [
{
title: '',
dataIndex: 'gdp',
width: 45,
render: () => '',
},
...colums,
];
// 獲取表格數據
const getData = () => {
setTableData([
{
id: 1,
province: '廣東省',
city: '',
area: '',
gdp: 7999,
},
{
id: 2,
province: '浙江省',
city: '',
area: '',
gdp: 6990,
},
{
id: 3,
province: '江蘇省',
city: '',
area: '',
gdp: 5990,
},
{
id: 4,
province: '北京市',
city: '',
area: '',
gdp: 8990,
},
{
id: 5,
province: '上海市',
city: '',
area: '',
gdp: 8999,
},
]);
};
useEffect(() => {
getData();
}, []);
// 市渲染
const provinceRender = (record: any) => {
// 如果表格數據沒變化,不會重新調接口,這里不需要再判斷是否有值
// 獲取城市數據
const getCitys = async () => {
const res = await getCityList(record.province);
return {
data: res,
};
};
// 區渲染
const cityRender = (row: any) => {
// 獲取區數據
const getAreas = async () => {
const res = await getAreaList(row);
return {
data: res,
};
};
return (
<ProTable
bordered
columns={colums2}
rowKey="id"
search={false}
request={getAreas}
pagination={false}
toolBarRender={false}
showHeader={false}
/>
);
};
return ( // 渲染的數據可以自定義
<ProTable
bordered
columns={colums}
rowKey="id"
search={false}
request={getCitys}
expandable={{
expandedRowRender: cityRender,
// expandedRowKeys: cityRowKeys,
// onExpandedRowsChange: cityExpandedRowsChange
}}
pagination={false}
toolBarRender={false}
showHeader={false}
/>
);
};
return (
<ProTable
bordered
columns={colums}
rowKey="id"
search={false}
dataSource={tableData}
expandable={{
expandedRowRender: provinceRender,
// expandedRowKeys: provinceRowKeys, // 如果需要篩選, 每次調用接口時將展開項收起,需要將expandedRowKeys屬性設為可控,
// onExpandedRowsChange: provinceExpandedRowsChange
}}
pagination={false}
toolBarRender={false}
/>
)
}
export default TreeTable;
這種方法不需要處理原始表格數據, 缺點是交互樣式差一點, 展開按鈕都在最左側, 不能通過是否有下一級來區別展示展開圖標
總結: 這兩種方式都可以異步獲取子級數據,具體用那種可以根據實際應用場景選擇
antd table的文檔說明
