Vue - vxe-table 表格合并行应用

vxe-table 地址:https://vxetable.cn/v2/#/table/start/install

一. 将相同的列数据合并为一行

实现效果

在这里插入图片描述

实现方法

使用 API 中的 span-method 方法:

在这里插入图片描述

  1. span-method 使用方法
    <vxe-grid
      border
      resizable
      align="center"
      :columns="tableColumn"
      :data="tableData"
      :span-method="rowspanMethod"
    >
    </vxe-grid>
    
    // 将相同的列数据合并为一行
    rowspanMethod({ row, _rowIndex, column, visibleData }) {
      // 需要合并的列字段
      let fields = [];
      const cellValue = row[column.property];
      if (cellValue && fields.includes(column.property)) {
        const prevRow = visibleData[_rowIndex - 1];
        let nextRow = visibleData[_rowIndex + 1];
        if (prevRow && prevRow[column.property] === cellValue) {
          return { rowspan: 0, colspan: 0 };
        } else {
          let countRowspan = 1;
          while (nextRow && nextRow[column.property] === cellValue) {
            nextRow = visibleData[++countRowspan + _rowIndex];
          }
          if (countRowspan > 1) {
            return { rowspan: countRowspan, colspan: 1 };
          }
        }
      }
    }
    
  2. 完整代码
    <template>
      <div class="page">
        <vxe-grid
          border
          resizable
          align="center"
          :columns="tableColumn"
          :data="tableData"
          :span-method="rowspanMethod"
        >
        </vxe-grid>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          tableColumn: [
            { type: "seq", field: "seq", width: 50 },
            { field: "bus", title: "公交班次" },
            { field: "upDown", title: "上下行" },
            { field: "strStation", title: "进站" },
            { field: "endStation", title: "出站" },
            { field: "guestNum", title: "上下行总客数" }
          ],
          tableData: [
            {
              bus: "1路",
              upDown: "上行",
              strStation: "B站",
              endStation: "A站",
              guestNum: 98
            },
            {
              bus: "1路",
              upDown: "下行",
              strStation: "A站",
              endStation: "B站",
              guestNum: 98
            },
            {
              bus: "2路",
              upDown: "下行",
              strStation: "C站",
              endStation: "B站",
              guestNum: 95
            },
            {
              bus: "2路",
              upDown: "上行",
              strStation: "B站",
              endStation: "C站",
              guestNum: 95
            },
            {
              bus: "3路",
              upDown: "上行",
              strStation: "B站",
              endStation: "D站",
              guestNum: 95
            },
            {
              bus: "3路",
              upDown: "下行",
              strStation: "D站",
              endStation: "B站",
              guestNum: 95
            },
            {
              bus: "4路",
              upDown: "下行",
              strStation: "D站",
              endStation: "C站",
              guestNum: 102
            },
            {
              bus: "4路",
              upDown: "上行",
              strStation: "C站",
              endStation: "D站",
              guestNum: 102
            }
          ]
        };
      },
      methods: {
        // 将相同的列数据合并为一行
        rowspanMethod({ row, _rowIndex, column, visibleData }) {
          // 需要合并的列字段
          let fields = ["bus", "upDown", "strStation", "endStation", "guestNum"];
          const cellValue = row[column.property];
          if (cellValue && fields.includes(column.property)) {
            const prevRow = visibleData[_rowIndex - 1];
            let nextRow = visibleData[_rowIndex + 1];
            if (prevRow && prevRow[column.property] === cellValue) {
              return { rowspan: 0, colspan: 0 };
            } else {
              let countRowspan = 1;
              while (nextRow && nextRow[column.property] === cellValue) {
                nextRow = visibleData[++countRowspan + _rowIndex];
              }
              if (countRowspan > 1) {
                return { rowspan: countRowspan, colspan: 1 };
              }
            }
          }
        }
      }
    };
    </script>
    <style scoped>
    .page {
      width: 100%;
      height: 100%;
      padding: 20px;
      box-sizing: border-box;
    }
    </style>
    

二. 拓展合并:根据某个字段合并后的数据 进行合并其他字段列

需求: 排序字段 根据 公交班次 合并后的数据进行排序,上下行总客数 根据 公交班次 合并后的数据

实现效果

在这里插入图片描述

实现方法

使用 API 中的 span-methodseq-config 方法:

在这里插入图片描述
在这里插入图片描述

  1. span-methodseq-config 使用方法

    <vxe-grid
      border
      resizable
      align="center"
      :columns="tableColumn"
      :data="tableData"
      :span-method="rowspanMethod"
      :seq-config="{ seqMethod }"
    >
    </vxe-grid>
    

    columns 列配置 中的排序项 需要添加field: "seq"

    tableColumn: [
      { type: "seq", field: "seq", width: 50 },
      { field: "bus", title: "公交班次" },
      { field: "upDown", title: "上下行" },
      { field: "strStation", title: "进站" },
      { field: "endStation", title: "出站" },
      { field: "guestNum", title: "上下行总客数" }
    ],
    
    /**
     *自定义合并:根据某个字段合并后的数据 进行合并其他字段列
     */
    rowspanMethod({
      row,
      items,
      seq,
      rowIndex,
      $rowIndex,
      _rowIndex,
      column,
      visibleData,
      data
    }) {
      /**
       * 相同的列数据 自定义合并
       * 此处自定义合并的字段:seq、guestNum
       * 此处的合并参考字段:bus
       */
      if (column.property === "seq") {
        // 合并参考字段,根据此字段进行合并行
        const referenceField = "bus";
        if (rowIndex > 0) {
          if (row[referenceField] === items[rowIndex - 1][referenceField]) {
            row.seq = items[rowIndex - 1].seq;
          } else {
            row.seq = items[rowIndex - 1].seq + 1;
          }
        } else if (rowIndex === 0) {
          row.seq = seq;
        }
        let prevRow = data[$rowIndex - 1];
        let nextRow = data[$rowIndex + 1];
        if (prevRow && prevRow[referenceField] === row[referenceField]) {
          return { rowspan: 0, colspan: 0 };
        } else {
          let countRowspan = 1;
          while (nextRow && nextRow[referenceField] === row[referenceField]) {
            nextRow = data[++countRowspan + $rowIndex];
          }
          if (countRowspan > 1) {
            return { rowspan: countRowspan, colspan: 1 };
          }
        }
      } else {
        /**
         * 相同的列数据 默认合并
         * 此处合并的列字段:["bus"]
         */
        // 需要合并的列字段
        let fields = ["bus"];
        const cellValue = row[column.property];
        if (cellValue && fields.includes(column.property)) {
          const prevRow = visibleData[_rowIndex - 1];
          let nextRow = visibleData[_rowIndex + 1];
          if (prevRow && prevRow[column.property] === cellValue) {
            return { rowspan: 0, colspan: 0 };
          } else {
            let countRowspan = 1;
            while (nextRow && nextRow[column.property] === cellValue) {
              nextRow = visibleData[++countRowspan + _rowIndex];
            }
            if (countRowspan > 1) {
              return { rowspan: countRowspan, colspan: 1 };
            }
          }
        }
      }
    },
    /**
     * 自定义排序
     * 此处的合并参考字段:bus
     */
    seqMethod(obj) {
      // 合并参考字段
      const referenceField = "bus";
      obj.row.seq = obj.seq;
      if (obj.rowIndex > 0) {
        if (obj.seq - obj.items[obj.rowIndex - 1].seq > 1) {
          if (
            obj.row[referenceField] ===
            obj.items[obj.rowIndex - 1][referenceField]
          ) {
            obj.row.seq = obj.items[obj.rowIndex - 1].seq;
            return obj.items[obj.rowIndex - 1].seq;
          } else {
            obj.row.seq = obj.items[obj.rowIndex - 1].seq + 1;
            return obj.items[obj.rowIndex - 1].seq + 1;
          }
        } else {
          obj.row.seq = obj.items[obj.rowIndex - 1].seq + 1;
          return obj.items[obj.rowIndex - 1].seq + 1;
        }
      } else {
        return obj.seq;
      }
    }
    
  2. 完整代码

    <template>
      <div class="page">
        <vxe-grid
          border
          resizable
          align="center"
          :columns="tableColumn"
          :data="tableData"
          :span-method="rowspanMethod"
          :seq-config="{ seqMethod }"
        >
        </vxe-grid>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          tableColumn: [
            { type: "seq", field: "seq", width: 50 },
            { field: "bus", title: "公交班次" },
            { field: "upDown", title: "上下行" },
            { field: "strStation", title: "进站" },
            { field: "endStation", title: "出站" },
            { field: "guestNum", title: "上下行总客数" }
          ],
          tableData: [
            {
              bus: "1路",
              upDown: "上行",
              strStation: "B站",
              endStation: "A站",
              guestNum: 98
            },
            {
              bus: "1路",
              upDown: "下行",
              strStation: "A站",
              endStation: "B站",
              guestNum: 98
            },
            {
              bus: "2路",
              upDown: "下行",
              strStation: "C站",
              endStation: "B站",
              guestNum: 95
            },
            {
              bus: "2路",
              upDown: "上行",
              strStation: "B站",
              endStation: "C站",
              guestNum: 95
            },
            {
              bus: "3路",
              upDown: "上行",
              strStation: "B站",
              endStation: "D站",
              guestNum: 95
            },
            {
              bus: "3路",
              upDown: "下行",
              strStation: "D站",
              endStation: "B站",
              guestNum: 95
            },
            {
              bus: "4路",
              upDown: "下行",
              strStation: "D站",
              endStation: "C站",
              guestNum: 102
            },
            {
              bus: "4路",
              upDown: "上行",
              strStation: "C站",
              endStation: "D站",
              guestNum: 102
            }
          ]
        };
      },
      methods: {
        /**
         *自定义合并:根据某个字段合并后的数据 进行合并其他字段列
         */
        rowspanMethod({
          row,
          items,
          seq,
          rowIndex,
          $rowIndex,
          _rowIndex,
          column,
          visibleData,
          data
        }) {
          /**
           * 相同的列数据 自定义合并
           * 自定义合并的字段:seq、guestNum
           * 此处的合并参考字段:bus
           */
          if (column.property === "seq" || column.property === "guestNum") {
            // 合并参考字段,根据此字段进行合并行
            const referenceField = "bus";
            if (rowIndex > 0) {
              if (row[referenceField] === items[rowIndex - 1][referenceField]) {
                row.seq = items[rowIndex - 1].seq;
              } else {
                row.seq = items[rowIndex - 1].seq + 1;
              }
            } else if (rowIndex === 0) {
              row.seq = seq;
            }
            let prevRow = data[$rowIndex - 1];
            let nextRow = data[$rowIndex + 1];
            if (prevRow && prevRow[referenceField] === row[referenceField]) {
              return { rowspan: 0, colspan: 0 };
            } else {
              let countRowspan = 1;
              while (nextRow && nextRow[referenceField] === row[referenceField]) {
                nextRow = data[++countRowspan + $rowIndex];
              }
              if (countRowspan > 1) {
                return { rowspan: countRowspan, colspan: 1 };
              }
            }
          } else {
            /**
             * 相同的列数据 默认合并
             * 此处合并的列字段:["bus"]
             */
            // 需要合并的列字段
            let fields = ["bus"];
            const cellValue = row[column.property];
            if (cellValue && fields.includes(column.property)) {
              const prevRow = visibleData[_rowIndex - 1];
              let nextRow = visibleData[_rowIndex + 1];
              if (prevRow && prevRow[column.property] === cellValue) {
                return { rowspan: 0, colspan: 0 };
              } else {
                let countRowspan = 1;
                while (nextRow && nextRow[column.property] === cellValue) {
                  nextRow = visibleData[++countRowspan + _rowIndex];
                }
                if (countRowspan > 1) {
                  return { rowspan: countRowspan, colspan: 1 };
                }
              }
            }
          }
        },
        /**
         * 自定义排序
         * 此处的合并参考字段:bus
         */
        seqMethod(obj) {
          // 合并参考字段
          const referenceField = "bus";
          obj.row.seq = obj.seq;
          if (obj.rowIndex > 0) {
            if (obj.seq - obj.items[obj.rowIndex - 1].seq > 1) {
              if (
                obj.row[referenceField] ===
                obj.items[obj.rowIndex - 1][referenceField]
              ) {
                obj.row.seq = obj.items[obj.rowIndex - 1].seq;
                return obj.items[obj.rowIndex - 1].seq;
              } else {
                obj.row.seq = obj.items[obj.rowIndex - 1].seq + 1;
                return obj.items[obj.rowIndex - 1].seq + 1;
              }
            } else {
              obj.row.seq = obj.items[obj.rowIndex - 1].seq + 1;
              return obj.items[obj.rowIndex - 1].seq + 1;
            }
          } else {
            return obj.seq;
          }
        }
      }
    };
    </script>
    <style scoped>
    .page {
      width: 100%;
      height: 100%;
      padding: 20px;
      box-sizing: border-box;
    }
    </style>