Antd中表格customRender行列合并与插槽如何同时使用

字节探云者
• 阅读 13777

在近日的开发中遇到了需要将antd表格的列合并与插槽合并使用的问题,现整理如下:

antd行列合并

关于antd行列合并的实现,antd官方文档中有详细介绍:

表头只支持列合并,使用 column 里的 colSpan 进行设置。
表格支持行/列合并,使用 render 里的单元格属性 colSpan 或者 rowSpan 设值为 0 时,设置的表格不会渲染。

本文以行合并(纵向合并)为例:
关于rowSpan属性值的获取,我写了一个方法,仅供参考:

/*
** data - 即table的dataSource
** index - 需要被合并的属性名
*/
function getRowSpanList (data, index) {
 var RowSpanList = new Array(data.length)
 var x = ''
 var count = 0
 var startindex = 0
 for (var i = 0; i < data.length;i++) {
    var val = data[i][index]
    if (i === 0 ) {
      x = val
      count = 1
      RowSpanList[0] = 1
    } else {
      if (val === x) {
        count ++
        RowSpanList[startindex] = count
        RowSpanList[i] = 0
      } else {
        count = 1
        x = val
        startindex = i
        RowSpanList[i] = 1
      }
    }
  }
  return RowSpanList
}

在table的column的相应属性中做配置,此处以class为例:

column: [{
  title: '类型',
  key: 'class',
  dataIndex: 'class'
  customRender: (text, record, index) => {
    return {
     children: text,
     attrs: {
       rowSpan: record.classRowSpanValue //由上文中的方法获取,仅供参考
     }
    }
  }
},...]

再将对应的rowSpan值赋给dataSource中相应对象即可:

var classRowSpanList = getRowSpanList(dataSource, 'class')
for (var i = 0;i < dataSource.length; i++) {
  dataSource[i].classRowSpanValue = classRowSpanList[i]
}

至此已可以实现简单的行合并,效果如下:
Antd中表格customRender行列合并与插槽如何同时使用

如果需要实现下图所示的有主从关系的行合并(即不同的合并项之间有明显的先后关系,红色框的合并受蓝色框限定):
Antd中表格customRender行列合并与插槽如何同时使用

需要结合主要属性对次要属性设置rowSpan值,方法如下,仅供参考:

/*
** data - 即table的dataSource
** index - 需要被合并的属性名
** formatArr - 合并主要项的rowSpan数组,通过getRowSpanList方法获取
*/
function getRowSpanListByFormatter (data, index, formatArr) {
  var newArray = new Array(data.length)
  var startIndex, endIndex, val, counter
  for(var i = 0; i < data.length; i++) {
    if (formatArr[i] === 1) {
      newArray[i] = 1
    } else if (formatArr[i] === 0) {
      continue
    } else {
      // 内层遍历
      startIndex = i
      endIndex = i + formatArr[i] - 1
      val = data[startIndex][index]
      counter = 1
      for(var j = i + 1; j <= endIndex; j++) {
        var currentVal = data[j][index]
        if (val === currentVal) {
          // 当前位置的colspan值为0,计数器++
          newArray[j] = 0
          counter++
          newArray[startIndex] = counter
        } else {
          // 上次的col数量
          newArray[startIndex] = counter
          // 对比数据重置
          startIndex = j
          val = data[startIndex][index]
          counter = 1
          if (j === endIndex) {
            newArray[j] = counter
          }
        }
     }
    }
  }
  return newArray
}

再将对应的rowSpan值赋给dataSource中相应对象即可。
列合并同理。

行列合并与插槽同时使用

普通的table插槽是在column对象中配置scopedSlots: { customRender: 'xxx' },并在<a-table>标签中写相应的代码实现的,与此处关系不大,不做过多的介绍。

上文中提到,行列合并时要对customRender做配置,相应单元格的重写则需要写在customRender返回的children中,使用的是类似React的语法:

customRender: (text, record, index) => {
  return {
   children: text, // 这里
   attrs: {
     rowSpan: 2 
   }
  }
}

注意,在同时使用行列合并与插槽功能时column应放在组件的data()中,否则渲染会出错,具体原因我也不清楚,期待大佬解答

例子如下,我希望在实现行合并的同时对超出单元格的内容做省略处理,并使用a-tooltip组件实现鼠标悬浮显示:

column:[{
    title: '类型',
    key: 'class',
    dataIndex: 'class',
    customRender: (text,record) => {
      var childrenVal
      if (record.scZoneRowSpan === 0) {
        // 为被合并的项,不被显示,他的内容意义不大
        childrenVal = ''
      } else if (record.scZoneRowSpan === 1) {
        // 不合并、单独显示的项,超出单元格做省略处理
        // 插槽与HTML代码相同,只是Vue中的{{}} 要换成 {}
        // 在children中的HTML已不支持v-if等Vue指令所以需要判断一下
        if (text && text.length >= 9) {
          childrenVal = (
            <a-tooltip>
              <template slot="title">{text}</template>
              <div style="width: 133px;height:21px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">{text}</div>
            </a-tooltip>)
        } else {
          childrenVal = (<span> {text} </span>)
        }
      } else if (record.scZoneRowSpan >= 2) {
        // 合并项,因为有足够的高度,可以直接显示
        childrenVal = text
      } 
      return {
        children: childrenVal,
        attrs: {
          rowSpan: record.scZoneRowSpan
        }
      }
    }
}, ...]

效果如图:
Antd中表格customRender行列合并与插槽如何同时使用

如果需要对插槽中的元素添加事件:

 childrenVal = (<div onclick={()=>{this.clickHandler(record)}} >{text}</div>)// 此处clickHandler正常写在methods中即可

总结

Ant Desing Vue 真难用

第一次写文章,也不知道讲清楚了没有,欢迎交流指导,各位大佬多多包涵。

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
3年前
VBox 启动虚拟机失败
在Vbox(5.0.8版本)启动Ubuntu的虚拟机时,遇到错误信息:NtCreateFile(\\Device\\VBoxDrvStub)failed:0xc000000034STATUS\_OBJECT\_NAME\_NOT\_FOUND(0retries) (rc101)Makesurethekern
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Easter79 Easter79
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这