ant design table樹形數據children數據異步獲取


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的文檔說明

 


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM