Element 的 el-table 表格实现单元格合并

  • html 部分
html 复制代码
<template>
  <div class="index-wapper">
    <el-table :data="tableData" :span-method="objectSpanMethod" border>
      <el-table-column v-for="(item, index) in tableHeader" :key="index" :prop="item.prop" :label="item.label"
        :fixed="item.fixed" align="center"></el-table-column>
    </el-table>
  </div>
</template>
  • js 部分
javascript 复制代码
<script>
export default {
  name: "index-page",
  components: {},
  props: {},
  data() {
    return {
      tableHeader: [
        {
          prop: "country",
          label: "城市",
          fixed: true,
        },
        {
          prop: "title",
          label: "地区",
          fixed: true,
        },
        {
          prop: "data1",
          label: "1",
          fixed: false,
        },
        {
          prop: "data2",
          label: "2",
          fixed: false,
        },
        {
          prop: "data3",
          label: "3",
          fixed: false,
        },
        {
          prop: "data4",
          label: "4",
          fixed: false,
        },
        {
          prop: "data5",
          label: "5",
          fixed: false,
        },
      ],
      tableData: [
        {
          id: 1,
          country: "杭州",
          title: "滨江",
          data1: 0,
          data2: 1,
          data3: 0,
          data4: 1,
          data5: 0,
        },
        {
          id: 2,
          country: "杭州",
          title: "西湖",
          data1: 0,
          data2: 0,
          data3: 0,
          data4: 0,
          data5: 0,
        },
        {
          id: 3,
          country: "杭州",
          title: "余杭",
          data1: 0,
          data2: 1,
          data3: 0,
          data4: 1,
          data5: 1,
        },
        {
          id: 4,
          country: "长沙",
          title: "岳麓",
          data1: 0,
          data2: 0,
          data3: 0,
          data4: 0,
          data5: 1,
        },
        {
          id: 5,
          country: "长沙",
          title: "开福",
          data1: 1,
          data2: 1,
          data3: 0,
          data4: 1,
          data5: 0,
        },
      ],
      spanArr: [],
    };
  },
  mounted() {
    this.getSpanArr();
  },
  methods: {
    /**
     * 合并处理
     */
    getSpanArr() {
      const hLen = this.tableHeader.length;
      // i表示行,j表示列
      for (let i = 0; i < this.tableData.length; i++) {
        if (i === 0) {
          for (let j = 0; j < hLen; j++) {
            this.spanArr[i * hLen + j] = {
              rowspan: 1,
              colspan: 1,
            };
          }
        } else {
          // 当前和上一次的一样,合并所有列的相同数据单元格
          for (let j = 0; j < hLen; j++) {
            // 指定合并哪些列
            if (this.tableHeader[j].prop === "country") {
              // 哪些不合并,country不一样的,不合并
              if (
                this.tableData[i]["country"] !==
                this.tableData[i - 1]["country"]
              ) {
                this.spanArr[i * hLen + j] = {
                  rowspan: 1,
                  colspan: 1,
                };
              } else if (
                this.tableData[i][this.tableHeader[j].prop] ===
                this.tableData[i - 1][this.tableHeader[j].prop]
              ) {
                let beforeItem = this.spanArr[(i - 1) * hLen + j];
                this.spanArr[i * hLen + j] = {
                  rowspan: 1 + beforeItem.rowspan, // 合并几列
                  colspan: 1, // 合并几行
                };
                beforeItem.rowspan = 0;
                beforeItem.colspan = 0;
              } else {
                this.spanArr[i * hLen + j] = {
                  rowspan: 1,
                  colspan: 1,
                };
              }
            }
          }
        }
      }
      // 对数据进行倒序
      let stack = [];
      for (let i = 0; i < hLen; i++) {
        for (let j = 0; j < this.tableData.length; j++) {
          const spanItem = this.spanArr[j * hLen + i];
          if (spanItem) {
            if (spanItem.rowspan === 0) {
              stack.push(spanItem);
            }
            if (j !== 0 && spanItem.rowspan !== 0) {
              stack.push(spanItem);
              while (stack.length > 0) {
                let pop = stack.pop();
                let len = stack.length;
                this.spanArr[(j - len) * hLen + i] = pop;
              }
            }
          }
        }
      }
    },
    /**
     * 表合并规则
     */
    objectSpanMethod({ rowIndex, columnIndex }) {
      return this.spanArr[rowIndex * this.tableHeader.length + columnIndex];
    },
  },
  watch: {},
};
</script>
相关推荐
持久的棒棒君4 小时前
npm安装electron下载太慢,导致报错
前端·electron·npm
渔舟唱晚@5 小时前
大模型数据流处理实战:Vue+NDJSON的Markdown安全渲染架构
vue.js·大模型·数据流
crary,记忆6 小时前
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
前端·webpack·angular·angular.js
漂流瓶jz6 小时前
让数据"流动"起来!Node.js实现流式渲染/流式传输与背后的HTTP原理
前端·javascript·node.js
SamHou07 小时前
手把手 CSS 盒子模型——从零开始的奶奶级 Web 开发教程2
前端·css·web
我不吃饼干7 小时前
从 Vue3 源码中了解你所不知道的 never
前端·typescript
开航母的李大7 小时前
【中间件】Web服务、消息队列、缓存与微服务治理:Nginx、Kafka、Redis、Nacos 详解
前端·redis·nginx·缓存·微服务·kafka
Bruk.Liu7 小时前
《Minio 分片上传实现(基于Spring Boot)》
前端·spring boot·minio
鱼樱前端8 小时前
Vue3+d3-cloud+d3-scale+d3-scale-chromatic实现词云组件
前端·javascript·vue.js
q_19132846958 小时前
基于Springboot+Vue的办公管理系统
java·vue.js·spring boot·后端·intellij idea