Ant Design Vue Table 行合并的实现方式

首先封装实现函数如下

function getRowSpanCount (data, key, mainKey, target) {
  if (!Array.isArray(data)) return 1
  
  // 只取出筛选项
  const mainData = data.map(_ => {
return _[mainKey]
})

// 只取出筛选项
  data = data.map(_ => {
return _[key]
}) 

  let preValue = data[0]
  let mainValue = mainData[0]
  const res = [[preValue]] // 放进二维数组里
  let index = 0 // 二维数组下标
  for (let i = 1; i < data.length; i++) {
    if (data[i] === preValue && mainData[i] === mainValue) {
      // 相同放进二维数组
      res[index].push(data[i])
    } else {
      // 不相同二维数组下标后移
      index += 1
      res[index] = []
      res[index].push(data[i])
      preValue = data[i]
      mainValue = mainData[i]
    }
  }
  const arr = []
  res.forEach(_ => {
    const len = _.length
    for (let i = 0; i < len; i++) {
      arr.push(i === 0 ? len : 0)
    }
  })
  return arr[target]
}

应用实例如下:

const columnPickItem = [
        {
          title: '物料编号',
          dataIndex: 'itemno',
          customRender: (value, row, index) => {
            const obj = {
              children: value,
              attrs: {}
            }
            obj.attrs.rowSpan = getRowSpanCount(this.noPickingData, 'itemno', 'itemId', index)
            return obj
          }
        },
        {
          title: '物料名称',
          dataIndex: 'itemname',
          customRender: (value, row, index) => {
            const obj = {
              children: value,
              attrs: {}
            }
            obj.attrs.rowSpan = getRowSpanCount(this.noPickingData, 'itemname', 'itemId', index)
            return obj
          }
        },
        {
          title: '规格型号',
          dataIndex: 'specifiCation',
          customRender: (value, row, index) => {
            const obj = {
              children: value,
              attrs: {}
            }
            obj.attrs.rowSpan = getRowSpanCount(this.noPickingData, 'specifiCation', 'itemId', index)
            return obj
          }
        },
        {
          title: '待备料数量',
          dataIndex: 'allcount',
          customRender: (value, row, index) => {
            const obj = {
              children: value,
              attrs: {}
            }
            obj.attrs.rowSpan = getRowSpanCount(this.noPickingData, 'allcount', 'itemId', index)
            return obj
          }
        },
        {
          title: '已备料数',
          dataIndex: 'pickcount',
          customRender: (value, row, index) => {
            const obj = {
              children: value,
              attrs: {}
            }
            obj.attrs.rowSpan = getRowSpanCount(this.noPickingData, 'pickcount', 'itemId', index)
            return obj
          }
        },
        {
          title: '单套数量',
          dataIndex: 'routecount',
          customRender: (value, row, index) => {
            const obj = {
              children: value,
              attrs: {}
            }
            obj.attrs.rowSpan = getRowSpanCount(this.noPickingData, 'routecount', 'itemId', index)
            return obj
          }
        },
        {
          title: '所在仓库名称',
          dataIndex: 'warehousename'
        },
        {
          title: '所在仓库编号',
          dataIndex: 'warehouseno'
        },
        {
          title: '所在库位名称',
          dataIndex: 'locationname'
        },
        {
          title: '所在库位编号',
          dataIndex: 'locationno'
        },
        {
          title: '批次号',
          dataIndex: 'lotNo'
        },
        {
          title: '包装号',
          dataIndex: 'packNo'
        },
        {
          title: '批次在库数量',
          dataIndex: 'count'
        },
        {
          title: '供应商',
          dataIndex: 'clientname'
        },
        {
          title: '备料数量',
          dataIndex: 'pickingCount',
          scopedSlots: {
            customRender: 'pickingCount'
          }
        }
      ]

实现逻辑及实现思路如下:
1.首先明确在 Ant Design Vue Table 的框架下要实现每一列行合并的方法是:
以从上往下的顺序来看待一个table,每一列的column属性都需要配置一个customRender如下

    {
       title: '物料编号',
       dataIndex: 'itemno',
       customRender: (value, row, index) => {
         const obj = {
           children: value,
           attrs: {}
         }
         obj.attrs.rowSpan = getRowSpanCount(this.noPickingData, 'itemno', 'itemId', index)
         return obj
       }
     },

并且设置对应的rowSpan数值,每一列对应的每一行rowSpan设置的数值就决定了行与行之间的合并方式。如一共三列三行数据,第一列第一行的rowSpan设置为3,第一列其余两行rowSpan设置为0则第一列的一到三行就会进行合并。(tips:有多少条数据或者说有多少行,该列对应配置的customRender函数就会执行多少次)

2.在明确官方实现逻辑的基础上进行函数封装做到自定义指定:当不同行中的一个或多个字段相同的情况下才进行行合并
上面函数封装内容从上往下的大概逻辑是:
(1) 校验传入的table数据类型
(2) 以传入的key, mainKey或更多的参数作为过滤条件,得到由所有table数据过滤所得仅包含对应字段的数组
(3) 设置初始值,创建二维数组,遍历数据执行逻辑:第二条数据与第一条数据做对比,当所有对应值相等,则把第二条数据对应值push进第一条数据所在二维数组的元素数组中,然后第三条数据再与第一条数据进行同样对比逻辑,直到遇到与第一条数据不满足所有对应值相等时,则该条数据在二维数组中新增一个数组元素,并作为该数组元素的第一个元素。然后继续进行遍历,后面的将该条数据作为前者进行对比,后续逻辑都相同了
(4) 然后再遍历上述二维数组,拿到我们所需要的该列所有行进行合并时所对应的rowSpan数字数组
(5)最后通过传入的行index,相应返回该行在rowSpan数字数组中所对应的数字

3.最终我们使用封装函数的方式如下

{
  title: '物料编号',
  dataIndex: 'itemno',
  customRender: (value, row, index) => {
    const obj = {
      children: value,
      attrs: {}
    }
    obj.attrs.rowSpan = getRowSpanCount(this.noPickingData, 'itemno', 'itemId', index)
    return obj
  }
},
 

意为在物料编号这一列,只要出现itemno和itemId这两个字段同时相等时,则进行行合并

你可能感兴趣的:(vue.js,javascript,前端)