关于表格相同元素合并单元格的实例

自闭症网瘾萝莉.ら 提交于 2020-01-16 05:45:17

这个标题名字还真不好取,一般想要这种功能的还真不好搜到这篇内容,只能静待有缘人了。(有好的标题,可以留言,我改还不行么?)

最近公司有一个新的项目需求,要求的是合并单元格,看似也没什么难度,但实际操作起来,确实不好做。(但理解了里面的逻辑,也就几行代码的问题)

然后前几天在一次看群里面聊天的时候,发现其他人也遇到了这样的需求。

要求是这样的,先来张图片

就是这种效果,将红色框部分合并起来,看似很简单的,但是注意,我们的数据是动态的,数据量是非常庞大的。完成后的效果如下

以为我们现在的项目是用vue框架写的,刚开始尝试用vue的思想来解决,发现没法下手。最终还是操作dom来完成的。

首先从后端的数据,是要有一定规范的,其实我们可以把他看成是一种树状结构。但是后端给的数据,其实还是标准的结构,表格一个循环就能解析出来的

我这里的标题数据,跟内容数据是分开来的。

我对后端要求的数据结构是这样的。

标题部分:

TableTitle: ['标题1', '标题2', '标题3','标题1', '标题2', '标题3'],

 

内容部分:

TableBody: [
          {
            value : [
              {
                title: 't1',
                val: 'a1',
              },
              {
                title: 't2',
                val: 'b1',
              },
              {
                title: 't3',
                val: 'c1',
              },
              {
                title: 't4',
                val: 'd1',
              },
              {
                title: 't5',
                val: 'e1',
              },
              {
                title: 't6',
                val: 'f1',
              },
            ]
          }]

这是前端拿到的数据结构,

接下来是渲染数据,其实就一个循环就可以了(这里用的是基于vue的渲染形式)

    <table width="100%" border="0" id="table1">
     <thead class="tableTitle">
        <tr>
          <th v-for="item in TableTitle" :key="item">{{item}}</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(items, index) in TableBody" :key="index"> 
          <td v-for="item in items.value" :key="item.title">{{item.val}}</td>
        </tr> 
      </tbody>
    </table>

到这里,渲染出来的效果就是最上面的第一张图的效果;

那么如何完成我们想要的合并单元格的目的呢。接下来,就是本篇的核心代码的(其实也就几行)

 MergeCells (tableId, startRow, endRow, col) {
       const tb = document.getElementById(tableId);
        if (col >= tb.rows[0].cells.length) { 
        return;
        } 
        if (col == 0) {
          endRow = tb.rows.length-1;
        } 
        for (var i = startRow; i < endRow; i++) {
          if (tb.rows[startRow].cells[col].innerHTML == tb.rows[i + 1].cells[col].innerHTML){
            tb.rows[i + 1].cells[col].className = "hide";
            tb.rows[startRow].cells[col].rowSpan = (tb.rows[startRow].cells[col].rowSpan | 0) + 1;
            if(this.colorSet && col == 0) {
              tb.rows[i].className = "lightColor"
              tb.rows[i+1].className = "lightColor"
            }
            if (i == endRow - 1 && startRow != endRow) { 
              this.MergeCells(tableId, startRow, endRow, col + 1);
            }
          } else {
            this.MergeCells(tableId, startRow, i, col+1);
            this.colorSet = !this.colorSet;
            startRow = i + 1;
          }
        } 
      },

 

调用它。只需要执行 

this.MergeCells('table1',0,0,0);

其实用过canvas的小伙伴,应该是知道的,canvas是有x,y坐标这样的概念。其实在表格里面,也是有这样的概念,这才是我们操作合并单元格的核心

tb.rows[0].cells[0],表示的就是该表格第一行,第一列的那个单元格。

在这里面,我还遇到一个巨大的坑。(受html合并单元格思想的影响,但我们这使用js操作dom来完成的。)

普通合并单元格是这么玩的。

<table>
  <tr>
        <td   width= "25% "rowspan="2">   </td>  
        <td   width= "25% ">   </td>  
        <td   width= "25% ">   </td>  
        <td   width= "25% ">   </td> 
     </tr>
     <tr>
        <td   width= "25% ">   </td>  
        <td   width= "25% ">   </td>  
        <td   width= "25% ">   </td> 
     </tr>
</table>

但是我们在用js操作dom的时候,最好不要remove里面的<td>,不然,就会导致整个表格的 rows  cells 位置全部混乱,很难定位到自己想要的单元格。移除掉一种一个单元格,它后面的单元格 rows  cells 的坐标位置肯定发生变化

这个坑,我踩了半天

<table>
  <tr>
        <td   width= "25% "rowspan="2">   </td>  
        <td   width= "25% ">   </td>  
        <td   width= "25% ">   </td>  
        <td   width= "25% ">   </td> 
     </tr>
     <tr>
        <td   width= "25% " class="hide">   </td>  
        <td   width= "25% ">   </td>  
        <td   width= "25% ">   </td>  
        <td   width= "25% ">   </td> 
     </tr>
</table> 


css部分
.hide{
  display: none;  
}

只需要将他给隐藏掉就好了,这样既不影响占位,也不影响其他单元格的下标。

其实到这里就结束了。

其实在实际操作中,要用到好些功能,比如,单元格加个斑马线的样式,让用户一眼就能区分开。

还有我们的数据量非常庞大,还要做滚动触底加载的功能等等,这些都是很简单的了,就不写了。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!