动态渲染table表格

有一个表格的需求是:当选择的年份时表头展示的数据是1月-12月,当选择的是月份时展示的是1-31日,当点击月份或日期的时候要展示二级子表头

实现需求的难点就在于如何拼凑数据,因为我使用的element-plus,下面就说说是如何实现需求的吧表格需求

首先是拼凑表头数据(系统名称,1月-12月),即cols

<el-table
      ref="table"
      style="margin-top: 50px; height: 69vh"
      :data="tableData"
      :key="isUpdate"
      @row-click="handleRow"
      @header-click="handleHeader"
    >
      <el-table-column
        label="系统名称"
        prop="rowLabel"
        width="150"
        show-overflow-tooltip
      >
      </el-table-column>
      <el-table-column
        v-for="(col, index) in cols"
        :key="col"
        :prop="col.prop"
        :label="col.label"
        show-overflow-tooltip
        align="center"
      >
        <template v-if="col.subColumn">
          <el-table-column
            v-for="(sub, i) in col.subColumn"
            :key="sub"
            :label="sub"
            :width="sub.width"
            show-overflow-tooltip
            align="center"
          >
            <template #default="scope">
              <span>{{ scope.row["children" + index][i] }}</span>
            </template>
          </el-table-column>
        </template>
      </el-table-column>
    </el-table>

1.将cols拼凑成类似这样的数据:
[
{label: ‘01月’, prop: ‘list0’},
{label: ‘02月’, prop: ‘list1’},
{label: ‘03月’, prop: ‘list2’},
{label: ‘04月’, prop: ‘list3’},
{label: ‘年度’, prop: ‘total’},
]

2.接下来就要去处理tableData的数据了,需要将tableData处理成这样的格式:
[
{rowLabel:“智能工作台”, list0: 12, list1: 22, list3: 13, total: 37},
{rowLabel:“OP系统”, list0: 12, list1: 22, list3: 13, total: 37},
{rowLabel:“投资管家”, list0: 12, list1: 22, list3: 13, total: 37},
{rowLabel:“360系统”, list0: 12, list1: 22, list3: 13, total: 37},
]

第二步,实现点击表头月份展开详情

const handleHeader = (column: any) => {
  // 点击的非月份直接return
  if (isNaN(parseInt(column.label))) return;
  const index = cols.value.findIndex((item) => item.prop === "detail");
  if (index === -1) {
    // 如果没有详情,点击不展开
    if (!childrenLabels.value.length) return;
    cols.value.splice(parseInt(column.label), 0, {
      label: "生产缺陷状态",
      prop: "detail",
      width: "180",
      showOverflowTooltip: true,
      subColumn: childrenLabels, // 二级表头的数组, ["处理中", "新建", "已拒绝", "已修复", "关闭"]
    });
  } else {
    if (parseInt(column.label) !== index) {
      // 点击其他月份
      cols.value.splice(
        parseInt(column.label),
        0,
        cols.value.splice(index, 1)[0]
      );
    } else {
      cols.value.splice(index, 1);
    }
  }
  isUpdate.value = !isUpdate.value;
};

最后是处理行数据,赋值给tableData,要得到的数据类型是这样的:
[
{rowLabel:“智能工作台”, list0: 12, list1: 22, list3: 13, total: 37, children0:[1,2,3,4], children1:[0,0,0,0], children2:[1,2,2,2], children3: [3,3,3,3]},
{rowLabel:“OP系统”, list0: 12, list1: 22, list3: 13, total: 37, children0:[1,2,3,4], children1:[0,0,0,0], children2:[1,2,2,2], children3: [3,3,3,3]},
{rowLabel:“投资管家”, list0: 12, list1: 22, list3: 13, total: 37, children0:[1,2,3,4], children1:[0,0,0,0], children2:[1,2,2,2], children3: [3,3,3,3]},
{rowLabel:“360系统”, list0: 12, list1: 22, list3: 13, total: 37, children0:[1,2,3,4], children1:[0,0,0,0], children2:[1,2,2,2], children3: [3,3,3,3]},
]

// 处理行数据
const getRowData = (datasets: any[]) => {
  const dealDatasets = Object.keys(datasets).map((key) => {
    const data = datasets[key];
    const row: Record<string | number | symbol, any> = { rowLabel: key };
    let total = 0;
    data.forEach((item, index) => {
      row["list" + index] = item.total;
      row["children" + index] = item.children;
      total += item.total;
    });
    row.total = total;
    return row;
  });
  // 计算‘总计’行数据
  let result = {};
  dealDatasets.forEach((data) => {
    Object.keys(data).forEach((key) => {
      if (!result[key]) {
        if (key === "rowLabel") {
          result[key] = "总计";
        } else if (key.startsWith("children")) {
          result[key] = new Array(data[key].length).fill(0);
        } else {
          result[key] = 0;
        }
      }
    });
  });
  dealDatasets.forEach((data) => {
    Object.keys(data).forEach((key) => {
      if (key !== "rowLabel" && !key.startsWith("children")) {
        result[key] += data[key];
      } else if (key.startsWith("children")) {
        result[key] = result[key].map((val, index) => val + data[key][index]);
      }
    });
  });
  return [...dealDatasets, result];
};

实现这个需求的难点就在与要拿后端返回的数据去拼凑成自己要的那种数据类型

### 创建动态 Table 表头 在 Vue.js 和 ElementUI 的组合下,`el-table` 组件提供了强大的功能来处理表格数据。为了实现动态表头的效果,可以通过绑定 `columns` 数据到 `el-table-column` 来达到目的。 下面是一个简单的例子,展示了如何通过 JavaScript 动态设置表头: ```html <template> <div id="app"> <!-- 使用 v-for 循环生成列 --> <el-table :data="tableData" style="width: 100%"> <el-table-column v-for="(column, index) in columns" :key="index" :prop="column.prop" :label="column.label" :formatter="column.formatter" :render-header="column.renderHeader"> </el-table-column> </el-table> </div> </template> <script> export default { data() { return { // 定义表格的数据源 tableData: [ { date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' }, { date: '2016-05-02', name: 'John', address: 'New York No. 1 Lake Park' } ], // 动态配置的列信息 columns: [ { prop: 'date', label: '日期', formatter(row, column) { return row.date; } }, { prop: 'name', label: '姓名', formatter(row, column) { return row.name; }, renderHeader(h, { column }) { return h('span', {}, ['姓氏:', column.label])} }, { prop: 'address', label: '地址', formatter(row, column) { return row.address; }} ] }; } }; </script> ``` 在这个实例里,`v-for` 指令用于遍历 `columns` 数组中的每一项,并将其作为参数传递给 `<el-table-column>` 标签内的属性。这使得可以根据实际需求轻松调整表头的内容和样式[^1]。 对于更复杂的场景,比如想要添加一些交互式的操作按钮或者特殊的渲染逻辑,则可以利用 `render-header` 属性来自定义表头的表现形式[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值