Bootstrap Table 表头和表格内容不对齐

  • 前言
  • 原因
  • 解决方式
  • 思路一
  • 思路二
  • 思路三


前言

之前的一次开发中使用到了Bootstrap Table的组件,在使用过程中出现了表头与表格内容不能对齐的现象,当时为了及时处理采取了一些方式,后续有时间将这个问题解决掉,做一下记录。

原因

表头与表格内容的不对齐,原因在于Bootstrap Table在配置height属性后,会将原本表格(.fixed-table-body下的table)赋予margin-top:-40px的属性,将原本表格内容的表头进行位移,从而隐藏,同时在 .fixed-table-header 中生成一组新的表格充当表头。但是新的表头因为通过了bootstrap-table.js中的resetHeader方法以及padding的重新计算,导致了出现这种现象。

解决方式

思路一

根据某度搜索,会找到很多建议修改源码如下的方式

this.$tableHeader.show();
 this.resetHeader();
 padding += this.$header.outerHeight();

改为

this.$tableHeader.show();
 //this.resetHeader();
 //padding += this.$header.outerHeight();

通过禁止使原表格位移以及不生成新的表头来阻止这种现象的发生,但是这样的后果就是表格再也没有固定的表头,在高度一定的范围了,进行滑动滚轴会导致表头丢失,对于不需要固定表头的小伙伴这种方式可以使用一下。

思路二

当时的需求在于不可以出现表头和内容不对齐,并且需要固定表头,这时候就有了一个引申的解决方式。
思路一的基础上进行的优化,加入了拓展js(bootstrap-table-sticky-header.js),通过配置Bootstrap Table的属性参数,实现浮动表头的显示。

stickyHeader: true,
stickyHeaderOffsetY: 表格距顶部的距离+'px',

这样的好处在于,表格和内容对齐的情况下,放弃原有的固定表头,改为浮动表头,仍然可以实现需求;但是缺点在于浮动的表头在原生样式的展示上仍然存在问题,会有浮动浮出的视觉效果,给人的感觉与表格不为一个整体,其次浮动出的表头中会没有各个列之间的边线,但是为了项目尽快验收上线,从而采用了这种有损效果的方式。

思路三

到后期腾出时间进行整体优化时,仔细读了读源码,捋了捋思绪,决定对源码下刀,通过之前的分析,知道症结在于新表头与老表头宽度不同从而导致固定表头下不对齐,所以决定通过遍历新表头将同位次老表头的列宽赋予至新表头从而实现对齐。

首先,恢复思路一中修改掉的源码,如下

this.$tableHeader.show();
 this.resetHeader();
 padding += this.$header.outerHeight();

其次,Bootstrap Table中提供了很多事件与方法,但是为了避免使其他同事因为源码改动而做兼容,所以需要将修改的部分放在表格的每一次渲染中,包括但不限于加载,刷新,翻页,排序等等,通过捋源码发现,在resetHeader方法中发现操控新表头的方式是通过setTimeout的方式进行的实现,那么就简单了,因为不论哪种方式的渲染都需要对标头进行加载,所以将修改的方法卸载resetHeader就可以了,如下:

this.custimeoutId_ = setTimeout(function(){
	$('.fixed-table-header table th').each(function(i,n){
	       var _ow = Number(
	       				window.getComputedStyle(
	       					$('.fixed-table-body table th').eq(i)[0])
	       					.width
	       					.replace('px',''));
	   	$(n).css('width',_ow+'px');
	   	$(n).find('.fht-cell').css('width',_ow-1+'px');
	   })
}, this.$el.is(':hidden') ? 100 : 0);

里面的几个要点:

  1. 宽度的提取
    通过js或jQuery对Dom元素提取宽度时会存在精度不够的问题,例如div宽度为119.2px,通过style.width或者$.width()$.outWidth()等提取后会四舍五入,变为119px,会导致前端页面上显示出现偏差。所以采用window.getComputedStyle(Dom)的方式获取元素的所有属性,从而提取宽度。(V3以后的jQuery有对这部分进行修正)
  2. 宽度的赋值
    将老表头th的宽度不能直接赋值于新表头的th,原因在于新表头th中存在.fht-celldiv,宽度其实是通过它进行填充的,因为外边线存在有1px,所以在宽度的赋值上需要减去1。
  3. 定时启动时间
    跟原生表头判定时间保持一致,在显示效果以及渲染上可以保持同步。