el-table 动态计算合并行

原始表格及代码

html 复制代码
<el-table
  :data="tableData"
  class="myTable"
  header-row-class-name="tableHead"
>
  <el-table-column prop="date" label="日期"> </el-table-column>
  <el-table-column prop="name" label="姓名"> </el-table-column>
  <el-table-column prop="project" label="项目"> </el-table-column>
  <el-table-column prop="address" label="地址" min-width="200">
  </el-table-column>
</el-table>
javascript 复制代码
// 模拟数据接口请求并排序
getDataMock() {
  for (var i = 0; i < 10; i++) {
    let randomDay = Math.floor(Math.random() * 5 + 1);
    this.tableData.push({
      date: "2024-12-" + randomDay,
      name: "王小虎" + i,
      project: "项目" + i,
      address: "上海市普陀区金沙江路 " + i + " 弄",
    });
  }
  this.tableData.sort((a, b) => {
    let time1 = new Date(a.date).getTime();
    let time2 = new Date(b.date).getTime();
    return time1 - time2;
  });
},
css 复制代码
.myTable {
  width: 700px;
  margin: 0 auto;
  border-radius: 20px;
  .tableHead {
    .el-table__cell {
      background-color: #bee7c5;
      color: #264f30;
      border-bottom: none;
      &:first-child {
        background: #435f5b;
        color: #fff;
      }
    }
  }
  .el-table__body {
    .el-table__row {
      .el-table__cell {
        background: #f7f7f7;
        border-bottom: 1px solid #dcdcdc;
        &:first-child {
          background: #acb2d9;
          color: #32405b;
          font-weight: bold;
          border-bottom: 1px solid #32405b;
        }
      }
    }
  }
}

合并行

  • 需要动态计算表格数据的合并行数
  • 如图所示,需要得到如下的 rowspan
  • 计算表格数据每行的 rowspan
javascript 复制代码
// 动态计算合并行的索引
getTableDataSpan(arr) {
  let spanData = []; // 数据数组的 rowspan 集合
  // rowspan > 1,合并行
  // rowspan == 1,单独行,不参与合并
  // rowspan == 0,被合并的行
  let lastRowIndex = 0; // 记录索引
  arr.forEach((item, index) => {
    if (index == 0) {
      // 第一行,默认认为不参与合并,记录为 1
      spanData.push(1);
    } else {
      if (item.date == arr[index - 1].date) {
        // 当前行的 date 与上一行的 date 相同,即当前行 的 rowspan 需要被记为 0
        spanData.push(0);
        // 向前找上次记录的索引,即需要当前行合并过去的目标行,使目标行的 rowspan 值加一
        spanData[lastRowIndex] += 1;
      } else {
        // 当前行的 date 与上一行的 date 不相等,则当前行的 rowspan 记录为 1
        spanData.push(1);
        // 暂且记录一下 lastRowIndex
        // 如果下一行与当前行的 date 值相同,就会合并到当前行,否则会更新 lastRowIndex 的值,进行下次对比
        lastRowIndex = index;
      }
    }
  });
  return {
    spanData: spanData,
    lastRowIndex: lastRowIndex,
  };
},
  • 计算 span-method 属性
html 复制代码
 <el-table
   :data="tableData"
   class="myTable"
   header-row-class-name="tableHead"
   :span-method="spanMethod"
 >
 ...
javascript 复制代码
spanMethod({ row, column, rowIndex, columnIndex }) {
  if (columnIndex === 0) {
    // 只有第一列需要合并,所以限定为 columnIndex === 0
    // 获取当前行的 rowspan
    let rowspan = this.getTableDataSpan(this.tableData).spanData[rowIndex];
    let colspan = rowspan === 0 ? 0 : 1; // 被合并到其他行,需要为 colspan 赋值为 0,否则为 1
    return {
      rowspan: rowspan,
      colspan: colspan,
    };
  }
},

样式调整优化

  • 上述代码得到如下效果
  • 原因是被合并的行,删掉了首列,被赋予了 first-child 的样式
  • 调整样式,为首列元素动态赋予类名
html 复制代码
<el-table
  :data="tableData"
  class="myTable"
  header-row-class-name="tableHead"
  :span-method="spanMethod"
  :cell-class-name="cellClassName"
>
...
javascript 复制代码
cellClassName({ row, column, rowIndex, columnIndex }) {
 if (columnIndex === 0) {
    return "colorBox"; // 首列添加类名
  }
},
css 复制代码
.el-table__body {
.el-table__row {
   .el-table__cell {
     background: #f7f7f7;
     border-bottom: 1px solid #dcdcdc;
     &.colorBox {
       background: #acb2d9;
       color: #32405b;
       font-weight: bold;
       border-bottom: 1px solid #32405b;
     }
   }
 }
}
  • 效果如图,会发现,动态赋予的 colorBox 类名,并没有被加到被合并的行的首列元素上

完整代码段

html 复制代码
<template>
  <div class="tableBox">
    <el-table
      :data="tableData"
      class="myTable"
      header-row-class-name="tableHead"
      :span-method="spanMethod"
      :cell-class-name="cellClassName"
    >
      <el-table-column prop="date" label="日期"> </el-table-column>
      <el-table-column prop="name" label="姓名"> </el-table-column>
      <el-table-column prop="project" label="项目"> </el-table-column>
      <el-table-column prop="address" label="地址" min-width="200">
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
export default {
  name: "dataList",
  components: {},
  data() {
    return {
      tableData: [],
    };
  },
  mounted() {
    this.getDataMock();
  },
  methods: {
    getDataMock() {
      for (var i = 0; i < 10; i++) {
        let randomDay = Math.floor(Math.random() * 5 + 1);
        this.tableData.push({
          date: "2024-12-" + randomDay,
          name: "王小虎" + i,
          project: "项目" + i,
          address: "上海市普陀区金沙江路 " + i + " 弄",
        });
      }
      this.tableData.sort((a, b) => {
        let time1 = new Date(a.date).getTime();
        let time2 = new Date(b.date).getTime();
        return time1 - time2;
      });
    },
    cellClassName({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
        return "colorBox";
      }
    },
    spanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
        // 只有第一列需要合并,所以限定为 columnIndex === 0
        // 获取当前行的 rowspan
        let rowspan = this.getTableDataSpan(this.tableData).spanData[rowIndex];
        let colspan = rowspan === 0 ? 0 : 1; // 被合并到其他行,需要为 colspan 赋值为 0,否则为 1
        return {
          rowspan: rowspan,
          colspan: colspan,
        };
      }
    },
    // 动态计算合并行的索引
    getTableDataSpan(arr) {
      let spanData = []; // 数据数组的 rowspan 集合
      // rowspan > 1,合并行
      // rowspan == 1,单独行,不参与合并
      // rowspan == 0,被合并的行
      let lastRowIndex = 0; // 记录索引
      arr.forEach((item, index) => {
        if (index == 0) {
          // 第一行,默认认为不参与合并,记录为 1
          spanData.push(1);
        } else {
          if (item.date == arr[index - 1].date) {
            // 当前行的 date 与上一行的 date 相同,即当前行 的 rowspan 需要被记为 0
            spanData.push(0);
            // 向前找上次记录的索引,即需要当前行合并过去的目标行,使目标行的 rowspan 值加一
            spanData[lastRowIndex] += 1;
          } else {
            // 当前行的 date 与上一行的 date 不相等,则当前行的 rowspan 记录为 1
            spanData.push(1);
            // 暂且记录一下 lastRowIndex
            // 如果下一行与当前行的 date 值相同,就会合并到当前行,否则会更新 lastRowIndex 的值,进行下次对比
            lastRowIndex = index;
          }
        }
      });
      return {
        spanData: spanData,
        lastRowIndex: lastRowIndex,
      };
    },
  },
};
</script>
<style lang="less" scoped>
.tableBox {
  background: #fff;
  padding: 50px 0;
  /deep/ .myTable {
    width: 700px;
    margin: 0 auto;
    border-radius: 20px;
    .tableHead {
      .el-table__cell {
        background-color: #bee7c5;
        color: #264f30;
        border-bottom: none;
        &:first-child {
          background: #435f5b;
          color: #fff;
        }
      }
    }
    .el-table__body {
      .el-table__row {
        .el-table__cell {
          background: #f7f7f7;
          border-bottom: 1px solid #dcdcdc;
          &.colorBox {
            background: #acb2d9;
            color: #32405b;
            font-weight: bold;
            border-bottom: 1px solid #32405b;
          }
        }
      }
    }
  }
}
</style>
相关推荐
我码玄黄3 分钟前
JS设计模式之访问者模式
javascript·设计模式·访问者模式
noravinsc4 分钟前
js监控鼠标在浏览器外边的具体位置及点击操作
开发语言·javascript·计算机外设
城沐小巷8 分钟前
基于springboot+vue的高校校园交友交流平台设计和实现
vue.js·spring boot·交友
远洋录14 分钟前
前端性能优化实战:从加载到渲染的全链路提升
前端·人工智能·react
tester Jeffky28 分钟前
JavaScript 高级特性与 ES6 新特性:正则表达式的深度探索
javascript·正则表达式·es6
谢斯43 分钟前
【electron】electron forge + vite + vue + electron-release-server 自动更新客户端
javascript·vue.js·electron
伊丶二1 小时前
echarts图表自定义配置(二)——代码封装
javascript·vue·echarts·自定义echarts
雯0609~1 小时前
vue3-tp8-Element:对话框实现
前端·javascript·vue.js
雕花の刺猬1 小时前
UE4与WEB-UI通信
前端·ui·ue4·webui