Vue3 + Element Plus 开发网页,使用 el-table 表格组件完成横、列都是动态数据的渲染,并且动态数据中含有二级分类?

新手上路,请多包涵

大佬们,请问在 Vue3 + Element Plus 网页开发中,使用 el-table 表格组件能否实现如下图所示的复杂表格。

横、列都是动态,而且都含有2级(固定2级),且有单元格合并(如图),希望前端界大牛帮忙看一下!谢谢了!感谢!

太复杂了。。

数据结构毫无思路。

阅读 1.9k
avatarAI BotBETA
在 Vue3 + Element Plus 中,使用 el-table 表格组件可以实现您所描述的复杂表格。下面是一个基本的示例,展示如何实现动态数据和二级分类的渲染:

首先,确保您已经正确安装并导入了 Vue3 和 Element Plus。然后,您可以在组件中引入 el-table 和相关样式。

<template>
<el-table :data="tableData" style="width: 100%">

<el-table-column prop="date" label="日期" width="180"></el-table-column>
<el-table-column prop="name" label="姓名" width="180"></el-table-column>
<el-table-column prop="address" label="地址"></el-table-column>

</el-table>
</template>

<script>
import { ref } from 'vue';
import { ElTable, ElTableColumn } from 'element-plus';

export default {
components: {

ElTable,
ElTableColumn,

},
setup() {

const tableData = ref([
  { date: '2023-06-20', name: '张三', address: '上海市普陀区金沙江路 1518 弄' },
  { date: '2023-06-21', name: '李四', address: '上海市普陀区金沙江路 1517 弄' },
  // 其他数据...
]);

return { tableData };

},
};
</script>

在上面的示例中,我们创建了一个简单的 el-table,并使用 `prop` 属性将每个列与数据对象中的属性进行绑定。您可以根据需要添加更多列,并相应地调整 `prop` 和 `label` 属性。

要实现动态数据和二级分类,您可以在 `tableData` 中使用嵌套对象或数组来表示多级数据结构。例如:

const tableData = ref([
{

date: '2023-06-20',
name: '张三',
address: {
  street: '金沙江路',
  suburb: '1518 弄'
}

},
{

date: '2023-06-21',
name: '李四',
address: {
  street: '金沙江路',
  suburb: '1517 弄'
}

},
// 其他数据...
]);

在模板中,您可以使用 `el-table-column` 的 `span-method` 属性来实现单元格合并。这是一个函数,接受一个参数,表示当前单元格的行和列信息,您可以根据需要返回一个合并的单元格数组。例如:

<el-table :data="tableData" style="width: 100%">
<el-table-column prop="date" label="日期" width="180"></el-table-column>
<el-table-column prop="name" label="姓名" width="180"></el-table-column>
<el-table-column prop="address.street" label="街道"></el-table-column>
<el-table-column prop="address.suburb" label="小区"></el-table-column>
</el-table>

2 个回答

先看下效果图
image.png

这个需求主要点就是表格列动态渲染和行合并

html 代码

<el-table :span-method="arraySpanMethod" :data="tableData">
    <el-table-column
      label="派出组"
      align="center"
      prop="group"></el-table-column>
    <el-table-column
      label="累计生产单"
      align="center"
      prop="total"></el-table-column>
    <el-table-column
      label="案件主办"
      align="center"
      prop="person"></el-table-column>
    <el-table-column
      v-for="(item, index) in headerList"
      :key="index"
      :label="item.label"
      align="center"
      :prop="item.prop">
      <el-table-column
        v-for="(list, i) in item.subList"
        :key="i"
        :label="list.label"
        align="center"
        :prop="list.prop">
        <template #default="scope">{{
          scope.row[item.prop][list.prop]
        }}</template>
      </el-table-column>
    </el-table-column>
  </el-table>

js 代码

// 模拟后台返回的表格头部信息
const headerList = ref([
  {
    label: '达飞',
    prop: 'column1',
    subList: [
      {
        label: '保理当日',
        prop: 'day'
      },
      {
        label: '保理累计',
        prop: 'total'
      }
    ]
  },
  {
    label: '农行',
    prop: 'column2',
    subList: [
      {
        label: '农行秦分当日',
        prop: 'day'
      },
      {
        label: '农行秦分累计',
        prop: 'total'
      }
    ]
  }
])
// 模拟后台返回的表格数据信息
const tableData1 = ref([
  {
    group: '海港组',
    total: 123,
    person: 'aa',
    column1: {
      day: '500',
      total: 3000
    },
    column2: { day: 100, total: 3000 }
  },
  {
    group: '海港组',
    total: 123,
    person: 'bb',
    column1: {
      day: '500',
      total: 3000
    },
    column2: { day: 100, total: 3000 }
  },
  {
    group: '海港组',
    total: 123,
    person: 'cc',
    column1: {
      day: '500',
      total: 3000
    },
    column2: { day: 100, total: 3000 }
  },
  {
    group: '其他组',
    total: 123,
    person: 'cc',
    column1: {
      day: '500',
      total: 3000
    },
    column2: { day: 100, total: 3000 }
  },
  {
    group: '其他组',
    total: 123,
    person: 'cc',
    column1: {
      day: '500',
      total: 3000
    },
    column2: { day: 100, total: 3000 }
  },
  {
    group: '其他组',
    total: 234,
    person: 'cc',
    column1: {
      day: '500',
      total: 3000
    },
    column2: { day: 100, total: 3000 }
  }
])
const groupArr = ref([]) // 用于合并组
const groupPos = ref(0) // 合并行数默认值
const totalArr = ref([]) // 用于合并生产单
const totalPos = ref(0) // 合并生产单默认值

// 表格行合并方法
const merge = (tableData) => {
  // 要合并的数组的方法
  groupArr.value = []
  groupPos.value = 0
  totalArr.value = []
  totalPos.value = 0

  for (var i = 0; i < tableData.length; i++) {
    if (i === 0) {
      // 第一行必须存在
      groupArr.value.push(1)
      groupPos.value = 0

      totalArr.value.push(1)
      totalPos.value = 0
    } else {
      // 判断当前元素与上一个元素是否相同 this.groupPos是groupArr内容的序号
      if (tableData[i].group === tableData[i - 1].group) {
        groupArr.value[groupPos.value] += 1
        groupArr.value.push(0)
      } else {
        groupArr.value.push(1)
        groupPos.value = i
      }

      // 生产单合并
      if (
        tableData[i].total === tableData[i - 1].total &&
        tableData[i].group === tableData[i - 1].group
      ) {
        totalArr.value[totalPos.value] += 1
        totalArr.value.push(0)
      } else {
        totalArr.value.push(1)
        totalPos.value = i
      }
    }
  }
}
// 合并行
const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => {
  if (columnIndex === 0) {
    // 合并组
    const _row_1 = groupArr.value[rowIndex]
    const _col_1 = _row_1 > 0 ? 1 : 0 // 如果被合并了_row=0则它这个列需要取消
    return {
      rowspan: _row_1,
      colspan: _col_1
    }
  } else if (columnIndex === 1) {
    // 第二列的合并方法,合并生产单
    const _row_2 = totalArr.value[rowIndex]
    const _col_2 = _row_2 > 0 ? 1 : 0
    return {
      rowspan: _row_2,
      colspan: _col_2
    }
  }
}
merge(tableData.value)

基本上满足了需求,动态列还有其他字段可以按照格式添加,合并行目前支持前两列相同数据合并

多级表头和表格合并都是有的。但是性能一般都会有瓶颈。

解决办法就是虚拟列表。

但是 Element 好像没支持虚拟化。所以你这里可以直接换一个其他库


比如 vxe-table ,但是我没用过这个库

image.png

推荐问题