React使用antd对于复杂数据类型表的渲染

React使用antd对于复杂数据类型表的渲染

数据

 const table = [
      {
        firstType: '电器',
        results: [
          {
            secondType: '电视',
            list: [
              {
                name: '小米',
                number: 20,
                price: 800
              },
              {
                name: '长虹',
                number: 10,
                price: 500
              }
            ]
          },
          {
            secondType: '冰箱',
            list: [
              {
                name: '美的',
                number: 20,
                price: 1000
              },
              {
                name: '海尔',
                number: 10,
                price: 888
              }
            ]
          }
        ]
      },
      {
        firstType: '食物',
        results: [
          {
            secondType: '零食',
            list: [
              {
                name: '坚果',
                number: 50,
                price: 8
              },
              {
                name: '辣条',
                number: 80,
                price: 3
              }
            ]
          },
          {
            secondType: '生疏',
            list: [
              {
                name: '青菜',
                number: 100,
                price: 1
              }
            ]
          }
        ]
      }
    ]

方法1:表格行列合并

React使用antd对于复杂数据类型表的渲染

思路:将复杂的嵌套数据转换一条条的各自独立的数据,当其有相同的元素 对其合并

import React, { useState, useEffect } from 'react'
import { Table } from 'antd'

const spanTable = () => {
  const [tableData, setTableData] = useState<any[]>([])

  const getTableData = () => {
    const table = [
      {
        firstType: '电器',
        results: [
          {
            secondType: '电视',
            list: [
              {
                name: '小米',
                number: 20,
                price: 800
              },
              {
                name: '长虹',
                number: 10,
                price: 500
              }
            ]
          },
          {
            secondType: '冰箱',
            list: [
              {
                name: '美的',
                number: 20,
                price: 1000
              },
              {
                name: '海尔',
                number: 10,
                price: 888
              }
            ]
          }
        ]
      },
      {
        firstType: '食物',
        results: [
          {
            secondType: '零食',
            list: [
              {
                name: '坚果',
                number: 50,
                price: 8
              },
              {
                name: '辣条',
                number: 80,
                price: 3
              }
            ]
          },
          {
            secondType: '生疏',
            list: [
              {
                name: '青菜',
                number: 100,
                price: 1
              }
            ]
          }
        ]
      }
    ]

    setTableData(handleSpan(table))
  }

  // 表格合并方法
  const handleSpan = (table, type = 3) => {
    const newData: any[] = []
    // 合并
      // 处理合并表格数据
      table.map((item, i) => {
        if (item.results && item.results.length) {
          item.results.map((ss, si) => {
            if (ss.list && ss.list.length) {
              ss.list.map((tt, ti) =>{
                const newItem = {
                  index: i + 1,
                  id: Math.floor(Math.random() * 100),//可以引入 nanoid组件生成不重复的id
                  firstType: item.firstType,
                  secondType: ss.secondType,
                  ...tt
                }
                // 三级合并的行数,所有子级results的长度
                if (si === 0 && ti === 0) {
                  newItem.oneRowSpan = item.results.reduce((a, b) => {
                    // console.log(a, b)
                    return a + b.list.length
                  }, 0)
                }
                // 二级合并的行,当前子级list的长度
                if (ti === 0) {
                  newItem.twoRowSpan = ss.list.length
                }

                newData.push(newItem)
              })
            }
          })
        }
      })
    
    console.log(newData)
    return newData
  }

  useEffect(() => {
    getTableData()
  }, [])

  const colums = [
    {
      title: '排序',
      dataIndex: 'index',
      render: (value, row) => {
        const obj = {
          children: value,
          props: {
            rowSpan: 0
          },
        };
        // 三级合并
        if (row.oneRowSpan) {
          obj.props.rowSpan = row.oneRowSpan;
        }
        return obj;
      },
    },
    {
      title: '一级分类',
      dataIndex: 'firstType',
      render: (value, row) => {
        const obj = {
          children: value,
          props: {
            rowSpan: 0
          },
        };
        // 三级合并
        if (row.oneRowSpan) {
          obj.props.rowSpan = row.oneRowSpan;
        }

        return obj;
      },
    },
    {
      title: '二级分类',
      dataIndex: 'secondType',
      render: (value, row) => {
        const obj = {
          children: value,
          props: {
            rowSpan: 0
          },
        };
        // 二级合并
        if (row.twoRowSpan) {
          obj.props.rowSpan = row.twoRowSpan;
        }
        return obj;
      },
    },
    {
      title: '名称',
      dataIndex: 'name',
    },
    {
      title: '数量',
      dataIndex: 'number',
    },
    {
      title: '价格',
      dataIndex: 'price',
    },
  ]


  return (
    <div>
      <h3 style={{marginTop: '15px'}}>表格合并</h3>
      <Table
        bordered
        columns={colums}
        rowKey="id"
        dataSource={tableData}
        pagination={false}
       />
    </div>
  )
}

export default spanTable

缺点:当负载类型数据量很大时 不便对于数据进行分析

方法二:使用嵌套子表格对于数据渲染

嵌套子表格

React使用antd对于复杂数据类型表的渲染

React使用antd对于复杂数据类型表的渲染

代码

  • 可以运用方法一的方法,将数据类型修改成如下处理:

      const table: any =[
        {
          firstType: '电器',
          secondType: '电视',
          results: [
            {
              name: '小米',
              number: 20,
              price: 800
            },
            {
              name: '长虹',
              number: 10,
              price: 500
            }
           ]
        },
        {
          firstType: '电器',
          secondType: '冰箱',
          results: [
            {
              name: '美的',
              number: 20,
              price: 1000
            },
            {
              name: '海尔',
              number: 10,
              price: 888
            },
          ]
        },
        {
          firstType: '食物',
          secondType: '零食',
          results: [
            {
              name: '坚果',
              number: 50,
              prie: 8
            },
            {
              name: '辣条',
              number: 80,
              price: 3
            }
            ]
          },
          {
            firstType: '食物',
            secondType: '生疏',
            results: [
                {
                  name: '青菜',
                  number: 100,
                  price: 1
                }
              ]
            },
          ]
    
import React, { useEffect, useState } from 'react';
import { Table} from 'antd'
export default () => {
 
  const dataSource: any = [
    {
      key: '1',
      title: '餐饮酒店/服务员',
      number: '8家门店,共8人',
      time: '2020.05.25 15:35',
      childData: [
        {
          key: '1.1',
          jobTitle: '大桶大足浴-保安',
          num: '2人',
        },
        {
          key: '1.2',
          jobTitle: '大桶大足浴-保安',
          num: '5人',
        },
      ]
    },
    {
      key: '2',
      title: '餐饮酒店/收银员',
      number: '无门店,共5人',
      time: '2020.06.06 11:35',
      childData: [
        {
          key: '2.1',
          jobTitle: '大桶大足浴',
          num: '0人',
        },
        {
          key: '2.2',
          jobTitle: '大桶大足浴',
          num: '1人',
        },
      ]
    },
  ]
  const table: any =[
    {
      firstType: '电器',
      secondType: '电视',
      results: [
        {
          name: '小米',
          number: 20,
          price: 800
        },
        {
          name: '长虹',
          number: 10,
          price: 500
        }
       ]
    },
    {
      firstType: '电器',
      secondType: '冰箱',
      results: [
        {
          name: '美的',
          number: 20,
          price: 1000
        },
        {
          name: '海尔',
          number: 10,
          price: 888
        },
      ]
    },
    {
      firstType: '食物',
      secondType: '零食',
      results: [
        {
          name: '坚果',
          number: 50,
          prie: 8
        },
        {
          name: '辣条',
          number: 80,
          price: 3
        }
        ]
      },
      {
        firstType: '食物',
        secondType: '生疏',
        results: [
            {
              name: '青菜',
              number: 100,
              price: 1
            }
          ]
        },
      ]


  const parentColumns: any = [
    {
      title: '第一类',
      dataIndex: 'firstType',
      key: 'firstType',
    },
    {
      title: '第二类',
      dataIndex: 'secondType',
      key: 'secondType',
    },
  ]
  const expandedRowRender = (record: any, index: any, indent: any, expanded: any) => {
    const childData = record.results
    const childColumns: any = [
      {
        title: <span style={{ color: "green" }}>名称</span>,
        dataIndex: 'name',
        key: 'name'
      },
      {
        title: <span style={{ color: "green" }}>数量</span>,
        dataIndex: 'number',
        key: 'number'
      },
      {
        title: <span style={{ color: "green" }}>价格</span>,
        dataIndex: 'price',
        key: 'price'
      },
    ]
   
    return <Table columns={childColumns} dataSource={childData} pagination={false} />
  }


  return (
    <div>
      <Table columns={parentColumns} dataSource={table} expandable={{ expandedRowRender }}/>
    </div>
  );
}

暂时只能理解到这两种方法,但数据量增大的化,还是不够理想

上一篇:antd嵌套子表格


下一篇:《Antd踩坑记》Antd Tabs无法动态设置选中的tab页