Vue之vxe-table表格合并行应用指南

 更新时间:2026年07月11日 14:24:58   作者:风轻轻~  
想要表格相同列数据智能合并?vxe-table合并单元格教程来啦!本指南教你使用span-method灵活合并行,并深入讲解如何根据字段进行拓展合并与排序,点击即可掌握让表格显示更清晰的核心技巧

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

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

实现效果

实现方法

使用 API 中的 span-method 方法:

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 };
      }
    }
  }
}

完整代码

<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 方法:

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;
  }
}

完整代码

<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>

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • vue实现检测敏感词过滤组件的多种思路

    vue实现检测敏感词过滤组件的多种思路

    这篇文章主要介绍了vue编写检测敏感词汇组件的多种思路,帮助大家更好的理解和学习使用vue框架,感兴趣的朋友可以了解下
    2021-04-04
  • Vue3中keep-alive的使用及注意事项说明

    Vue3中keep-alive的使用及注意事项说明

    这篇文章主要介绍了Vue3中keep-alive的使用及注意事项说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • 仿照Element-ui实现一个简易的$message方法

    仿照Element-ui实现一个简易的$message方法

    这篇文章主要介绍了仿照Element-ui实现一个简易的$message方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • vuex 的简单使用

    vuex 的简单使用

    vuex是一个专门为vue.js设计的集中式状态管理架构。这篇文章主要介绍了vuex 的简单使用,需要的朋友可以参考下
    2018-03-03
  • vue使用$emit传递参数方式

    vue使用$emit传递参数方式

    这篇文章主要介绍了vue使用$emit传递参数方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • Vue之全局水印的实现示例

    Vue之全局水印的实现示例

    页面水印大家或许都不陌生,本文主要介绍了Vue之全局水印的实现示例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • Vue实现图片与文字混输效果

    Vue实现图片与文字混输效果

    用多了 JQuery ,习惯了使用JQuery的API操作 DOM ,几乎忘记了原生JS对DOM操作,今天在项目中遇到了文字和图片混输的情况,小编给大家分享Vue实现图片与文字混输效果,感兴趣的朋友一起看看吧
    2019-12-12
  • Vue对话框组件使用方法详解

    Vue对话框组件使用方法详解

    这篇文章主要为大家详细介绍了Vue对话框组件的使用方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Vue父组件调用子组件事件方法

    Vue父组件调用子组件事件方法

    下面小编就为大家分享一篇Vue父组件调用子组件事件方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-02-02
  • 详解使用vuex进行菜单管理

    详解使用vuex进行菜单管理

    本篇文章主要介绍了详解使用vuex进行菜单管理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12

最新评论