【前端】使用vue3 + el-table组件,实现合并行/列。

前言

在开发的过程中遇见一个需求,就是要求合并行。UI设计的效果图如下
在这里插入图片描述
大致需求就是, 1.将订单号、创建人、创建日期和操作列合并; 2.将父订单号合并。只是他们合并的逻辑不一样,前者这需要判断订单号一样就合并,而后者需要判断父订单号一样且订单号也一样时才合并。
这个需求倒是没有什么难度,项目用的是 vue3 + element Plus组件库开发的,所以我就去element官网逛了逛。链接如下,感兴趣的大佬可以自行跳转过去看看。
https://element-plus.org/zh-CN/component/table#%E5%90%88%E5%B9%B6%E8%A1%8C%E6%88%96%E5%88%97
在这里插入图片描述
el-table组件的 span-method 属性,接受一个函数, 用来计算合并行或列的方法。该方法有四个参数 row: any, column: any, rowIndex: number, columnIndex: number
以数组形式返回

const arraySpanMethod = ({
  row,
  column,
  rowIndex,
  columnIndex,
}: SpanMethodProps) => {
  if (rowIndex % 2 === 0) {
    if (columnIndex === 0) {
      return [1, 2]
    } else if (columnIndex === 1) {
      return [0, 0]
    }
  }
}

以对象形式返回

const objectSpanMethod = ({
  row,
  column,
  rowIndex,
  columnIndex,
}: SpanMethodProps) => {
  if (columnIndex === 0) {
    if (rowIndex % 2 === 0) {
      return {
        rowspan: 2,
        colspan: 1,
      }
    } else {
      return {
        rowspan: 0,
        colspan: 0,
      }
    }
  }
}

但是,官网的例子比较简单,合并逻辑还是得根据自己的需求写业务逻辑。
这里提供两种实现方式,实现逻辑有所区别,第一种是在合并方法里面写合并逻辑,第二种获取数据过后,将需要合并的数据先处理,在合并方法里面直接用处理好的数据。这里更推荐第二种,因为性能更好些。

代码实现

第一种实现方式(直接在合并方法里面些合并逻辑)

function spanMethod1({ row, column, rowIndex, columnIndex }) {
  // 合并的列,从0开始。这里是合并1、4、5、6列
  if ([1, 4, 5, 6].includes(columnIndex)) {
    console.log("进入打印")
    if (
      rowIndex === 0 || (
        rowIndex > 0 &&
        row.orderNo !== tableData.value[rowIndex - 1].orderNo
      )) {
      let rowspan = 1;
      for (let i = rowIndex + 1; i < tableData.value.length; i++) {
        console.log("循环打印")
        if (row.orderNo === tableData.value[i].orderNo) {
          rowspan++;
        } else {
          break;
        }
      }
      return [rowspan, 1];
    } else {
      return [0, 0];
    }
  }
}

这样的缺点是,只要页面大小发生变化,都会触发合并方法,对性能不友好。

Video_2025-03-02_131438

接下来是第二种(提前计算好合并逻辑,直接使用)

function spanMethod({ row, column, rowIndex, columnIndex }) {
  if ([1, 4, 5, 6].includes(columnIndex)) {
    console.log("进入打印")
    let rowSpan = mergeInfo.value.orderNos[rowIndex];
    const colSpan = rowSpan > 0 ? 1 : 0;
    return [rowSpan, colSpan];
  }
  if (columnIndex === 2) {
    let rowSpan = mergeInfo.value.children[rowIndex];
    const colSpan = rowSpan > 0 ? 1 : 0;
    return [rowSpan, colSpan];
  }
}

function handleMergeData() {
  let orderNoIndex = 0;
  let childrenIndex = 0;
  tableData.value.forEach((item, index) => {
    if (index === 0) {
      mergeInfo.value.orderNos.push(1);
      mergeInfo.value.children.push(1);
      orderNoIndex = 0;
      childrenIndex = 0;
    } else {
      if (item.orderNo === tableData.value[index - 1].orderNo) {
        mergeInfo.value.orderNos[orderNoIndex] += 1;
        mergeInfo.value.orderNos.push(0);
      } else {
        mergeInfo.value.orderNos.push(1);
        orderNoIndex = index;
      }
      if (item.orderNo === tableData.value[index - 1].orderNo &&
        item.parentOrderNo === tableData.value[index - 1].parentOrderNo
      ) {
        mergeInfo.value.children[childrenIndex] += 1;
        mergeInfo.value.children.push(0);
      } else {
        mergeInfo.value.children.push(1);
        childrenIndex = index;
      }
    }
  });
}

Video_2025-03-02_132800

从视频中可以直观的看出来,后者比前者性能更好些,每次渲染不用再次进行计算合并逻辑。

在ECharts的表格组件el-table)中,如果你想实现根据前一的值动态合并下一的功能,这通常涉及到数据处理和模板渲染。你需要在前端代码中做以下几个步骤: 1. **数据处理**: - 首先,检查数据源(如数组或对象),找出需要合并的规律。例如,如果某一的值连续相同,那么下一的数据应该合并到上一- 可能需要编写一个函数,遍历数据,识别并标记那些需要合并。 2. **模板配置**: - 使用Vue.js的`v-for`指令遍历处理后的数据,为每一生成HTML模板。 - 对于需要合并,可以设置`rowspan`属性来表示跨越多,同时确保其他的单元格值显示为空或其他默认值。 ```html <template> <el-table :data="processedData"> <el-table-column prop="header" label="标题"></el-table-column> <template v-for="(item, index) in processData" :key="index"> <el-table-row :row-class-name="{ &#39;merge-cell&#39;: shouldMerge(index, item.previousValue) }"> <el-table-cell v-if="!shouldMerge(index, item.previousValue)">{{ item.value }}</el-table-cell> <el-table-cell v-else rowspan="numberToBeMerged">{{ item.value }}</el-table-cell> </el-table-row> </template> </el-table> </template> <script> export default { data() { return { processedData: [...], // 处理后的数据 }; }, methods: { shouldMerge(index, previousValue) { // 判断当前项是否需要与前一项合并,条件依据实际情况而定 if (previousValue && previousValue === this.processedData[index - 1].value) { return true; } return false; }, numberToBeMerged() { // 计算需要合并数,也取决于具体的规则 // 返回1意味着不需要合并,根据实际规则修改此部分 return 1; }, }, }; </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值