最近有一个产品需求是需要一个有合并单元格场景的表格展示数据,但是element-ui合并单元格作为一个前端菜鸟也是没有用过,所以只能抱着探索的心态是看了下表格的知识。首先看下产品的原型图

 

element合并之后数据不对 elementui表格合并单元格_vue.js



从图中可以看出时间和支付渠道为apple 和总计的属性需要合并行,其实可以兼容成所有的渠道都可以合并,如果看了element-ui 关于table 的使用的话,应该清楚单元格合并需要的两个元素,一个是合并的列的索引一个是需要合并的行数(几行合并为一行)还有就是从哪一行开始合并。

从图中可以看到我们需要合并的哪一列是明确的,那么难点就是如何确定从哪一行开始合并以及合并多少行呢。

 

tableData: [
        {
          date: "2021/08/23",
          chanel: "微信",
          diamond: 99,
          should_pay: 100,
          real_pay: 100,
          trade_type: "人民币",
          due: 23,
          final_get: 1000
        },
        {
          date: "2021/08/23",
          chanel: "apple",
          diamond: 99,
          should_pay: 100,
          real_pay: 100,
          trade_type: "人民币",
          due: 23,
          final_get: 1000
        },
        {
          date: "2021/08/23",
          chanel: "apple",
          diamond: 99,
          should_pay: 100,
          real_pay: 100,
          trade_type: "美元",
          due: 23,
          final_get: 1000
        },
        {
          date: "2021/08/23",
          chanel: "总计",
          diamond: 99,
          should_pay: 100,
          real_pay: 100,
          trade_type: "人民币",
          due: 23,
          final_get: 1000
        },
        {
          date: "2021/08/23",
          chanel: "总计",
          diamond: 99,
          should_pay: 100,
          real_pay: 100,
          trade_type: "美元",
          due: 23,
          final_get: 1000
        },
        {
          date: "2021/08/24",
          chanel: "支付宝",
          diamond: 100,
          should_pay: 100,
          real_pay: 100,
          trade_type: "人民币",
          due: 23,
          final_get: 1000
        },
        {
          date: "2021/08/24",
          chanel: "总计",
          diamond: 99,
          should_pay: 100,
          real_pay: 100,
          trade_type: "美元",
          due: 23,
          final_get: 1000
        }
      ]

 上面是我造的假数据,在后续的操作中会添加一些辅助字段在里面

let temp_data_list = [];

    for (let j = 0; j < this.tableData.length; j++) {
      if (j !== 0) {
        if (this.tableData[j].date !== this.tableData[j - 1].date) {
          this.tableData[j].isCanMerageDate = true;
          let info = {
            date: this.tableData[j].date,
            dateLength: 1
          };
          temp_data_list.push(info);
        } else {
          //两条date 相同则数量加1
          for (let i = 0; i < temp_data_list.length; i++) {
            if (temp_data_list[i].date === this.tableData[j].date) {
              temp_data_list[i].dateLength += 1;
            }
          }
        }

        if (this.tableData[j].chanel !== this.tableData[j - 1].chanel) {
          this.tableData[j].isCanMerageChanel = true;
          let chanel_info = {
            chanel: this.tableData[j].chanel,
            date: this.tableData[j].date,
            chanelLength: 1
          };
          temp_data_list.push(chanel_info);
        } else {
          for (let i = 0; i < temp_data_list.length; i++) {
            if (temp_data_list[i].chanel === this.tableData[j].chanel) {
              temp_data_list[i].chanelLength += 1;
            }
          }
        }
      } else {
        this.tableData[0].isCanMerageDate = true;
        this.tableData[0].isCanMerageChanel = true;

        let info = {
          date: this.tableData[0].date,
          dateLength: 1,
          chanelLength: 1,
          chanel: this.tableData[0].chanel
        };
        temp_data_list.push(info);
      }
    }

 temp_data_list 是整合后的符合条件的信息的集合

第一条数据也就是j=0 时候,第一条的日期,和渠道一定是可以向下合并的,只不过合并的行数有可能是1。所以此时的渠道和日期 isCanMerageDate和isCanMerageChanel 都为true 即 此条可以向下合并行

当j>0 的时候,如果前后两条数据的日期不一致,那么需要把后一条的时间保存,并且可以合并的日期长度记为1 ;

当前后两条数据的日期一致的时候,需要遍历已经保存的合并消息,当两条日期相当的时候把合并长度加1。

同理渠道的信息获取和日期的一致

当操作完这个列表的时候我们看下此时的temp_data_list

element合并之后数据不对 elementui表格合并单元格_vue.js_02

 我们已经拿到了我们想要的数据集合,结下来就需要把对应的合并信息补充到 tableData 里,其实主要补充的是合并的长度
 

for (let i = 0; i < temp_data_list.length; i++) {
      for (let j = 0; j < this.tableData.length; j++) {
        if (
          this.tableData[j].isCanMerageDate &&
          temp_data_list[i].date === this.tableData[j].date &&
          !isNaN(temp_data_list[i].dateLength)
        ) {
          this.tableData[j].date_length = temp_data_list[i].dateLength;
        }
        if (
          this.tableData[j].isCanMerageChanel &&
          temp_data_list[i].chanel === this.tableData[j].chanel &&
            temp_data_list[i].date === this.tableData[j].date
        ) {
          this.tableData[j].chanel_length = temp_data_list[i].chanelLength;
        }
      }
    }

新的tabledata 的数据结构大体是这个样子

element合并之后数据不对 elementui表格合并单元格_element合并之后数据不对_03

 最后我们需要绑定自定义的合并方法
 

<el-table
        :data="tableData"
        border
        :span-method="objectSpanMethod"
        style="width: 100%"
      >
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
          return {
            rowspan: row.isCanMerageDate?row.date_length:0,
            colspan: 1
          };
      } else if (columnIndex === 1) {
          return {
            rowspan: row.isCanMerageChanel?row.chanel_length:0,
            colspan: 1
          };

      }
    }

最后看下运行效果

element合并之后数据不对 elementui表格合并单元格_javascript_04


 

 大功告成