制作一个多层表头的实现

工作终到了多重表头,所以就用vue简单写了一个。以前也写过,但是感觉这次写的比较简单一些,所以就总结下。

html 复制代码
<template>
  <div class="exeicise-boxs">
    <table>
      <colgroup>
        <template v-for="h in colMsgList">
          <col :width="h.width" :key="Date.now() + h.prop" />
        </template>
      </colgroup>
      <thead>
        <tr v-for="(rows, rowIndex) in tableHeaderList" :key="rowIndex">
          <th
            v-for="header in rows"
            :key="header.props"
            :rowspan="header.rowSpan"
            :colspan="header.colSpan"
          >
            {{ header.title }}
          </th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(data, index) in tableDatas" :key="index + 'data'">
          <template v-for="col in colMsgList">
            <td :key="col.prop">{{ data[col.prop] }}</td>
          </template>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  created() {
    this.multiTableHeaderHander(this.tableHeaders, 3); // 需要手动告诉函数,这次处理的几个层级的表头
    console.log(
      "multiTableHeaderHander",
      this.tableHeaderList,
      this.colMsgList
    );
  },
  methods: {
    multiTableHeaderHander(headerList, rowNum, initNum = 1) {
      // 处理多层表头数据成为多个数组组成的Map()数据
      const headerArr = [];
      headerList.forEach(h => {
        if (!h.chlidren) {
          headerArr.push({
            ...h,
            rowSpan: rowNum,
            colSpan: 1
          });
          this.colMsgList.push({
            width: h.width,
            prop: h.prop
          });
        } else {
          const child = this.multiTableHeaderHander(
            h.chlidren,
            rowNum - 1,
            initNum + 1
          );
          headerArr.push({
            ...h,
            rowSpan: 1,
            colSpan: child.map(c => c.colSpan).reduce((pre, cur) => pre + cur)
          });
        }
      });
      if (this.tableHeaderMap.get(initNum)) {
        this.tableHeaderMap.set(initNum, [
          ...this.tableHeaderMap.get(initNum),
          ...headerArr
        ]);
      } else {
        this.tableHeaderMap.set(initNum, [...headerArr]);
      }
      return headerArr;
    }
  },
  computed: {
    tableHeaderList() {
      // 把Map()转化成为数组,便于遍历。
      const arr = [];
      this.tableHeaderMap.forEach((value, key) => {
        arr[key - 1] = value;
      });
      return arr;
    }
  },
  data() {
    return {
      colMsgList: [], //在递归的时候,收集每个展示信息数据td的宽度和prop。
      tableHeaderMap: new Map(), //用来把不通层级的表头数据,用[]分隔开,有利于后期的表头的循环遍历
      tableHeaders: [
        // 表头内容
        { title: "序号", prop: "seqNo", width: 60 },
        {
          title: "班级",
          width: 500,
          chlidren: [
            { title: "班号", prop: "classNm", width: 100 },
            {
              title: "学生",
              chlidren: [
                { title: "姓名", prop: "name", width: 80 },
                { title: "性别", prop: "gender", width: 60 },
                { title: "总分", prop: "grade", width: 60 },
                { title: "爱好", prop: "hobby", width: 200 }
              ]
            }
          ]
        },
        {
          title: "各科成绩汇总",
          width: 180,
          chlidren: [
            { title: "语文", prop: "chinese", width: 60 },
            { title: "数学", prop: "math", width: 60 },
            { title: "英语", prop: "english", width: 60 }
          ]
        },
        {
          title: "各科老师评价",
          width: 360,
          chlidren: [
            { title: "语文老师", prop: "chineseT", width: 90 },
            { title: "数学老师", prop: "mathT", width: 90 },
            { title: "英语老师", prop: "englishT", width: 90 }
          ]
        },
        { title: "年级主任总结", prop: "directorComment", width: 200 }
      ],
      tableDatas: [
        //标题数据
        {
          seqNo: 1,
          classNm: "三年二班",
          name: "huyi",
          gender: "男",
          grade: "294",
          hobby: "唱跳rapper,篮球",
          chinese: "98",
          math: "98",
          english: "98",
          chineseT: "比较懒",
          mathT: "比较聪明",
          englishT: "记忆里还可以",
          directorComment: "也就那样继续努力"
        }
      ]
    };
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
table {
  border-collapse: collapse;
}
table th,
table td {
  padding: 10px;
  border: 1px solid #000;
}
th {
  background: #ccc;
}
</style>

数据处理为:

实现效果如下:

相关推荐
小满zs3 小时前
Zustand 第五章(订阅)
前端·react.js
涵信4 小时前
第一节 基础核心概念-TypeScript与JavaScript的核心区别
前端·javascript·typescript
谢尔登4 小时前
【React】常用的状态管理库比对
前端·spring·react.js
编程乐学(Arfan开发工程师)4 小时前
56、原生组件注入-原生注解与Spring方式注入
java·前端·后端·spring·tensorflow·bug·lua
小公主4 小时前
JavaScript 柯里化完全指南:闭包 + 手写 curry,一步步拆解原理
前端·javascript
姑苏洛言6 小时前
如何解决答题小程序大小超过2M的问题
前端
GISer_Jing7 小时前
JWT授权token前端存储策略
前端·javascript·面试
开开心心就好7 小时前
电脑扩展屏幕工具
java·开发语言·前端·电脑·php·excel·batch
拉不动的猪7 小时前
es6常见数组、对象中的整合与拆解
前端·javascript·面试
GISer_Jing7 小时前
Vue Router知识框架以及面试高频问题详解
前端·vue.js·面试