黄春亮 发表于 2023-7-15 13:53:55

el-table表格动态合并相同数据单元格(可指定列+自定义合并)

1.固定合并


[*]官方挺提供的合并具体某行列的方法:el-table合并行或列
[*]通过给table传入span-method方法可以实现合并行或列,方法的参数是一个对象,里面包含当前行row、当前列column、当前行号rowIndex、当前列号columnIndex四个属性。
该函数可以返回一个包含两个元素的数组,第一个元素代表rowspan,第二个元素代表colspan。 也可以返回一个键名为rowspan和colspan的对象。
<template>
<div>
    <el-table
      :data="tableData"
      :span-method="arraySpanMethod"
      border
      style="width: 100%">
      <el-table-column
      prop="id"
      label="ID"
      width="180">
      </el-table-column>
      <el-table-column
      prop="name"
      label="姓名">
      </el-table-column>
      <el-table-column
      prop="amount1"
      sortable
      label="数值 1">
      </el-table-column>
      <el-table-column
      prop="amount2"
      sortable
      label="数值 2">
      </el-table-column>
      <el-table-column
      prop="amount3"
      sortable
      label="数值 3">
      </el-table-column>
    </el-table>
    <el-table
      :data="tableData"
      :span-method="objectSpanMethod"
      border
      style="width: 100%; margin-top: 20px">
      <el-table-column
      prop="id"
      label="ID"
      width="180">
      </el-table-column>
      <el-table-column
      prop="name"
      label="姓名">
      </el-table-column>
      <el-table-column
      prop="amount1"
      label="数值 1(元)">
      </el-table-column>
      <el-table-column
      prop="amount2"
      label="数值 2(元)">
      </el-table-column>
      <el-table-column
      prop="amount3"
      label="数值 3(元)">
      </el-table-column>
    </el-table>
</div>
</template>
<script>
export default {
    data() {
      return {
      tableData: [{
          id: '12987122',
          name: '王小虎',
          amount1: '234',
          amount2: '3.2',
          amount3: 10
      }, {
          id: '12987123',
          name: '王小虎',
          amount1: '165',
          amount2: '4.43',
          amount3: 12
      }, {
          id: '12987124',
          name: '王小虎',
          amount1: '324',
          amount2: '1.9',
          amount3: 9
      }, {
          id: '12987125',
          name: '王小虎',
          amount1: '621',
          amount2: '2.2',
          amount3: 17
      }, {
          id: '12987126',
          name: '王小虎',
          amount1: '539',
          amount2: '4.1',
          amount3: 15
      }]
      };
    },
    methods: {
      arraySpanMethod({ row, column, rowIndex, columnIndex }) {
      if (rowIndex % 2 === 0) {
          if (columnIndex === 0) {
            return ;
          } else if (columnIndex === 1) {
            return ;
          }
      }
      },
      objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
          if (rowIndex % 2 === 0) {
            return {
            rowspan: 2,
            colspan: 1
            };
          } else {
            return {
            rowspan: 0,
            colspan: 0
            };
          }
      }
      }
    }
};
</script>运行效果:


缺点:这种只适合写死的数据和固定的表格行列,无法动态判断单元格数据是否相等再合并;

2. 动态合并相同数据单元格(所有列)


[*]可以对所有相同数据的列,进行动态合并
[*]此方法适合需要合并所有的相同数据的单元格
<template>
<div>
    <el-table
      :data="tableData"
      :span-method="objectSpanMethod"
      border
      :header-cell-style="{ textAlign: 'center', backgroundColor: '#F5F7FA' }"
    >
      <el-table-column prop="School" label="学校" align="center">
      </el-table-column>
      <el-table-column prop="Grade" label="年级" align="center" />
      <el-table-column prop="Class" label="班级" align="center" />
      <el-table-column prop="Name" label="姓名" align="center" />
      <el-table-column prop="Chinese" label="语文" align="center" />
      <el-table-column prop="Math" label="数学" align="center" />
      <el-table-column prop="English" label="英语" align="center" />
    </el-table>
</div>
</template>
<script>
export default {
data() {
    return {
      // 存放所有的表头 一定要与tableData一致
      colFields: [
      "School",
      "Grade",
      "Class",
      "Name",
      "Chinese",
      "Math",
      "English",
      ],
      spanArr: [], //存储合并单元格的开始位置
      // 表格数据
      tableData: [
      // 一年级
      {
          School: "第一小学",
          Grade: "1年级",
          Class: "1班",
          Name: "张三",
          Chinese: "90",
          Math: "100",
          English: "80",
      },
      {
          School: "第一小学",
          Grade: "1年级",
          Class: "2班",
          Name: "李四",
          Chinese: "90",
          Math: "85",
          English: "80",
      },
      {
          School: "第一小学",
          Grade: "1年级",
          Class: "3班",
          Name: "王五",
          Chinese: "79",
          Math: "100",
          English: "80",
      },
      // 二年级
      {
          School: "第一小学",
          Grade: "2年级",
          Class: "1班",
          Name: "赵六",
          Chinese: "95",
          Math: "100",
          English: "80",
      },
      {
          School: "第一小学",
          Grade: "2年级",
          Class: "2班",
          Name: "钱八",
          Chinese: "98",
          Math: "85",
          English: "80",
      },
      {
          School: "第一小学",
          Grade: "2年级",
          Class: "3班",
          Name: "陈九",
          Chinese: "79",
          Math: "100",
          English: "80",
      },
      // 三年级
      {
          School: "第一小学",
          Grade: "3年级",
          Class: "1班",
          Name: "黄十",
          Chinese: "91",
          Math: "88",
          English: "80",
      },
      {
          School: "第一小学",
          Grade: "3年级",
          Class: "2班",
          Name: "魏一",
          Chinese: "90",
          Math: "86",
          English: "87",
      },
      {
          School: "第一小学",
          Grade: "3年级",
          Class: "3班",
          Name: "杨二",
          Chinese: "79",
          Math: "99",
          English: "80",
      },
      ],
    };
},
methods: {
    /**
   * 分析每一列,找出相同的
   * @param data
   */
    getSpanArr() {
      for (let i = 0; i < this.tableData.length; i++) {
      let row = i;
      // let col = i % this.colCount;
      if (row === 0) {
          // i 表示行 j表示列
          for (let j = 0; j < this.colFields.length; j++) {
            this.spanArr = {
            rowspan: 1,
            colspan: 1,
            };
          }
      } else {
          for (let j = 0; j < this.colFields.length; j++) {
            // 当前和上一次的一样
            // 1. 合并所有列的相同数据单元格
            if (
            this.tableData] ===
            this.tableData]
            ) {
            let beforeItem =
                this.spanArr[(row - 1) * this.colFields.length + j];
            this.spanArr = {
                rowspan: 1 + beforeItem.rowspan, // 合并几行
                colspan: 1, // 合并几列,我这里只是跨行合并,不跨列合并,所以用的1
            };
            beforeItem.rowspan = 0;
            beforeItem.colspan = 0;
            } else {
            // rowspan 和 colspan 都为1表格此单元格不合并
            this.spanArr = {
                rowspan: 1,
                colspan: 1,
            };
            }
          }
      }
      }
      // 对数据进行倒序
      let stack = [];
      for (let i = 0; i < this.colFields.length; i++) {
      for (let j = 0; j < this.tableData.length; j++) {
          // console.log("i=" + i + " j=" + j);
          // i 表示列 j表示行
          if (j === 0) {
            if (this.spanArr.rowspan === 0) {
            stack.push(this.spanArr);
            }
          } else {
            if (this.spanArr.rowspan === 0) {
            stack.push(this.spanArr);
            } else {
            stack.push(this.spanArr);
            while (stack.length > 0) {
                let pop = stack.pop();
                let len = stack.length;
                this.spanArr[(j - len) * this.colFields.length + i] = pop;
            }
            }
          }
      }
      }
      // console.log(this.spanArr);
    },
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      // console.log(this.spanArr);
      return this.spanArr;
    },
},
mounted() {
    this.getSpanArr();
},
};
</script>
<style lang="scss" scoped></style>效果:

我们可以看到,所有列,只要数据相同的单元格都被合并了,包括我不想合并的单元格,这时候就要指定合并的列了


3. 动态合并相同数据单元格(指定列)

只需要加个if判断即可指定要合并哪些列
// 这里只放了部分代码,除了加了个if,其他代码和上面的一样
getSpanArr() {
      for (let i = 0; i < this.tableData.length; i++) {
      let row = i;
      // let col = i % this.colCount;
      if (row === 0) {
          // i 表示行 j表示列
          for (let j = 0; j < this.colFields.length; j++) {
            this.spanArr = {
            rowspan: 1,
            colspan: 1,
            };
          }
      } else {
          for (let j = 0; j < this.colFields.length; j++) {
            // 当前和上一次的一样
            //合并所有列的相同数据单元格
            if (
            this.colFields == "School" ||
            this.colFields == "Grade" ||
            this.colFields == "Class"
            ) { // 指定合并哪些列
            if (
                this.tableData] ===
                this.tableData]
            ) {
                let beforeItem =
                  this.spanArr[(row - 1) * this.colFields.length + j];
                this.spanArr = {
                  rowspan: 1 + beforeItem.rowspan,
                  colspan: 1,
                };
                beforeItem.rowspan = 0;
                beforeItem.colspan = 0;
            } else {
                // rowspan 和 colspan 都为1表格此单元格不合并
                this.spanArr = {
                  rowspan: 1,
                  colspan: 1,
                };
            }
            }
          }
      }
      }效果:这样就只合并了我们指定的那几列了


4. 动态合并相同数据单元格(指定列+合并条件)

有时候我们会遇到不想合并的单元格,比如下面这种情况:

按常理来说,不同小学的数据应该是不做合并才对,正确是这种:

这时候就需要加上一些自定义的合并条件了:
getSpanArr() {
      for (let i = 0; i < this.tableData.length; i++) {
      let row = i;
      // let col = i % this.colCount;
      if (row === 0) {
          // i 表示行 j表示列
          for (let j = 0; j < this.colFields.length; j++) {
            this.spanArr = {
            rowspan: 1,
            colspan: 1,
            };
          }
      } else {
          for (let j = 0; j < this.colFields.length; j++) {
            // 当前和上一次的一样
            //合并所有列的相同数据单元格
            if (
            this.colFields == "School" ||
            this.colFields == "Grade" ||
            this.colFields == "Class"
            ) { // 指定合并哪些列
            if (
                this.tableData["School"] !==
                  this.tableData["School"]
            ) { // 哪些不合并:School不一样的,不合并
                this.spanArr = {
                  rowspan: 1,
                  colspan: 1,
                };
            } else if (
                this.tableData] ===
                this.tableData]
            ) {
                let beforeItem =
                  this.spanArr[(row - 1) * this.colFields.length + j];
                this.spanArr = {
                  rowspan: 1 + beforeItem.rowspan,// 合并几列
                  colspan: 1,// 合并几行
                };
                beforeItem.rowspan = 0;
                beforeItem.colspan = 0;
            } else {
                // rowspan 和 colspan 都为1表格此单元格不合并
                this.spanArr = {
                  rowspan: 1,
                  colspan: 1,
                };
            }
            }
          }
      }
      }
      // console.log(this.spanArr);
    },这时候再看,就是我们想要的效果了


完整代码

最后附完整代码:
<template>
<div>
    <el-table
      :data="tableData"
      :span-method="objectSpanMethod"
      border
      :header-cell-style="{ textAlign: 'center', backgroundColor: '#F5F7FA' }"
    >
      <el-table-column prop="School" label="学校" align="center">
      </el-table-column>
      <el-table-column prop="Grade" label="年级" align="center" />
      <el-table-column prop="Class" label="班级" align="center" />
      <el-table-column prop="Name" label="姓名" align="center" />
      <el-table-column prop="Chinese" label="语文" align="center" />
      <el-table-column prop="Math" label="数学" align="center" />
      <el-table-column prop="English" label="英语" align="center" />
    </el-table>
</div>
</template>
<script>
export default {
data() {
    return {
      // 存放所有的表头 一定要与tableData一致
      colFields: [
      "School",
      "Grade",
      "Class",
      "Name",
      "Chinese",
      "Math",
      "English",
      ],
      spanArr: [], //存储合并单元格的开始位置
      // 表格数据
      tableData: [
      // 一年级
      {
          School: "第一小学",
          Grade: "1年级",
          Class: "1班",
          Name: "张三",
          Chinese: "90",
          Math: "100",
          English: "80",
      },
      {
          School: "第一小学",
          Grade: "1年级",
          Class: "1班",
          Name: "张伟",
          Chinese: "90",
          Math: "99",
          English: "89",
      },
      {
          School: "第一小学",
          Grade: "1年级",
          Class: "2班",
          Name: "李四",
          Chinese: "90",
          Math: "85",
          English: "80",
      },
      {
          School: "第一小学",
          Grade: "1年级",
          Class: "3班",
          Name: "王五",
          Chinese: "79",
          Math: "100",
          English: "80",
      },
      // 二年级
      {
          School: "第一小学",
          Grade: "2年级",
          Class: "1班",
          Name: "赵六",
          Chinese: "95",
          Math: "100",
          English: "80",
      },
      {
          School: "第一小学",
          Grade: "2年级",
          Class: "2班",
          Name: "钱八",
          Chinese: "98",
          Math: "85",
          English: "80",
      },
      {
          School: "第一小学",
          Grade: "2年级",
          Class: "3班",
          Name: "陈九",
          Chinese: "79",
          Math: "100",
          English: "100",
      },
      // 三年级
      {
          School: "第一小学",
          Grade: "3年级",
          Class: "1班",
          Name: "黄十",
          Chinese: "91",
          Math: "88",
          English: "80",
      },
      {
          School: "第一小学",
          Grade: "3年级",
          Class: "2班",
          Name: "魏一",
          Chinese: "90",
          Math: "86",
          English: "87",
      },
      {
          School: "第一小学",
          Grade: "3年级",
          Class: "3班",
          Name: "杨二",
          Chinese: "79",
          Math: "99",
          English: "80",
      },
      // 第二小学
      {
          School: "第二小学",
          Grade: "3年级",
          Class: "3班",
          Name: "袁零",
          Chinese: "79",
          Math: "99",
          English: "80",
      },
      ],
    };
},
methods: {
    /**
   * 分析每一列,找出相同的
   * @param data
   */
    getSpanArr() {
      for (let i = 0; i < this.tableData.length; i++) {
      let row = i;
      // let col = i % this.colCount;
      if (row === 0) {
          // i 表示行 j表示列
          for (let j = 0; j < this.colFields.length; j++) {
            this.spanArr = {
            rowspan: 1,
            colspan: 1,
            };
          }
      } else {
          for (let j = 0; j < this.colFields.length; j++) {
            // 当前和上一次的一样
            //合并所有列的相同数据单元格
            if (
            this.colFields == "School" ||
            this.colFields == "Grade" ||
            this.colFields == "Class"
            ) { // 指定合并哪些列
            if (
                this.tableData["School"] !==
                  this.tableData["School"]
            ) { // 哪些不合并:School不一样的,不合并
                this.spanArr = {
                  rowspan: 1,
                  colspan: 1,
                };
            } else if (
                this.tableData] ===
                this.tableData]
            ) {
                let beforeItem =
                  this.spanArr[(row - 1) * this.colFields.length + j];
                this.spanArr = {
                  rowspan: 1 + beforeItem.rowspan,// 合并几列
                  colspan: 1,// 合并几行
                };
                beforeItem.rowspan = 0;
                beforeItem.colspan = 0;
            } else {
                // rowspan 和 colspan 都为1表格此单元格不合并
                this.spanArr = {
                  rowspan: 1,
                  colspan: 1,
                };
            }
            }
          }
      }
      }
      // 对数据进行倒序
      let stack = [];
      for (let i = 0; i < this.colFields.length; i++) {
      for (let j = 0; j < this.tableData.length; j++) {
          // console.log("i=" + i + " j=" + j);
          // i 表示列 j表示行
          if (j === 0) {
            if (this.spanArr.rowspan === 0) {
            stack.push(this.spanArr);
            }
          } else {
            if (this.spanArr.rowspan === 0) {
            stack.push(this.spanArr);
            } else {
            stack.push(this.spanArr);
            while (stack.length > 0) {
                let pop = stack.pop();
                let len = stack.length;
                this.spanArr[(j - len) * this.colFields.length + i] = pop;
            }
            }
          }
      }
      }
      // console.log(this.spanArr);
    },
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      // console.log(this.spanArr);
      return this.spanArr;
    },
},
mounted() {
    this.getSpanArr();
},
};
</script>
<style lang="scss" scoped></style>参考:https://blog.csdn.net/u010735120/article/details/122184493
到此这篇关于el-table表格动态合并相同数据单元格(可指定列+自定义合并)的文章就介绍到这了,更多相关el-table 动态合并单元格内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

来源:https://www.jb51.net/javascript/292180wz4.htm
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: el-table表格动态合并相同数据单元格(可指定列+自定义合并)