1.在做表格拆分之前我们先理解一下BootStrap Table合并单元格的原理,
1.table初始化时会按照基础样式加载所有数据,即一行一行的很规矩的表格
2.通过rowspan属性改变该字段合并的行数,他会覆盖其他的行,而不是加宽此行(重要)
2.我们来看一下网友提供的代码,然后我们在分析一下其中可能出现的问题
1.配置bootstrapTable加载选项 onLoadSuccess
onLoadSuccess: function (data) {
mergeCells(data, "fieldName", 1, $('#table')); },
2.声明mergeCells函数,如:
/** * 合并单元格 * @param data 原始数据(在服务端完成排序) * @param fieldName 合并属性名称 * @param colspan 合并列 * @param target 目标表格对象$("table") */ function mergeCells(data,fieldName,colspan,target){ //声明一个map计算相同属性值在data对象出现的次数和 var sortMap = {}; for(var i = 0 ; i < data.length ; i++){ //data 为后台查询数据 for(var prop in data[i]){ //data[i]具体对象,prop为对象的属性名 if(prop == fieldName){ //fiedName为我们要合并的字段名 var key = data[i][prop] //key 为fiedName字段对应的值 if(sortMap.hasOwnProperty(key)){ sortMap[key] = sortMap[key] * 1 + 1; } else { sortMap[key] = 1; } break; } } } for(var prop in sortMap){ console.log(prop,sortMap[prop]) } var index = 0; for(var prop in sortMap){//sortMap是以字段值为key,该值出现的次数为值得 map var count = sortMap[prop] * 1; $(target).bootstrapTable('mergeCells',{index:index, field:fieldName, colspan: colspan, rowspan: count}); index += count; } }
3.代码分析:
1.通过一个map记录fiedName字段的值(key)出现的次数,用index记录位置, 然后通过for循环去设置
rowspan的值,而rowspan的值count来源于sortMap,
4.可能出现的问题
1.我们看到他的本意map有序,但其实map是无序的,这就可能导致合并行的值是错的,从而覆盖了其他
的值。例如map里有{ key1:1,key2:3,key3:2}即:key1出现1次,key2出现3次,key3出现2次那么我们期望
的结果是:第1行显示key1,第2-4行显示key2,第5-6行显示key3;但实际从map中取值是随机的,可能会出
现第1-3行显示key1,第4-5行显示key2,第6行显示key3的情况;更糟的是,现在我们看到的map中的值可能
压根就不是我们放入时的顺序。所以这个单元格合并一定是有问题的。
5.如何解决
1.首先因为单元格合并会覆盖其他行的值,所以我们要确保被覆盖的值是相同的,也就说我们后台传来的list
必须保证相同数据严格相邻
2.我们在确保list有序之后,必须保证map中的值和出现的次数是有序的即:从1开始key1出现1次,从2开始
key2出现3次,从5开始key3出现2次,只有map有序我们才能保证后面for循环合并单元格操作的正确性(其
实我们可以不关心 ”值”,只要确保“值”出现的“次数”是有序的就行)但是map是无序的,可以考虑用数组代
替具体实现可随意发挥
3.据我所知,BootStrap Table应该是不支持单元格拆分的,只能实现单元格合并,那么假如一张表有20个字
段,我们要拆分一个字段,那么我们只能反向合并其他19个字段。(如果哪位大哥有好的方法,欢迎推荐)
6.单元格拆分的实现,反向合并:
function mergeCells(data,fieldName,colspan,target){ //声明一个map计算相同属性值在data对象出现的次数和 var sortMap = {}; for(var i = 0 ; i < data.length ; i++){ for(var prop in data[i]){ if(prop == fieldName){ var key = data[i][prop] if(sortMap.hasOwnProperty(key)){ sortMap[key] = sortMap[key] * 1 + 1; } else { sortMap[key] = 1; } break; } } } for(var prop in sortMap){ console.log(prop,sortMap[prop]) } var index = 0; var fiedArry = ["checkbox","index","cmtText","flightNo","flightDate","orderNo","cmtLevel","emotion","remark","cmtTime"];//除了要拆分的那一个字段之外的另外19个字段 for(var prop in sortMap){ var count = sortMap[prop] * 1; fiedArry.forEach(function(field) {//19个字段全部做单元格合并操作 $(target).bootstrapTable('mergeCells',{index:index, field:field, colspan: colspan, rowspan: count}); }); index += count; } }
7.用list替换map的解决方案
function mergeCells(data,fieldName,colspan,target){ //声明一个map计算相同属性值在data对象出现的次数和 var sortMap = {}; var valueArry = new Array();//数组只记录值 for(var i = 0 ; i < data.length ; i++){ for(var prop in data[i]){ if(prop == fieldName){ var key = data[i][prop] valueArry[i] = key; break; } } } var numArry = new Array();//记录值出现的次数 一会就通过循环次数组 合并单元格 var value = valueArry[0] ;//初始值 var num = 0 ;//记录值出现的次数 var index1 = 0 ;//numArry的下标 for(var i = 0 ; i <= valueArry.length ; i++){ if(i == valueArry.length){//解决最后一次赋值 numArry[index1] = num; break; } if(value == valueArry[i] ){ num++;//list下一个值与变量value值相同时,num+1,下标不变 }else{ value = valueArry[i];//如果值不相等就把下一个值 赋值给value变量 numArry[index1] = num;//把value变量之前的值 出现的次数记录下来 num = 1 ;// 新的value值出现一次 index1++;//下标+1; } } for(var prop in sortMap){ console.log(prop,sortMap[prop]) } var index = 0; var fiedArry = ["checkbox","index","cmtText","flightNo","flightDate","orderNo","cmtLevel","emotion","remark","cmtTime"]; for(var i = 0 ; i < valueArry.length ; i++){ var count = numArry[i] * 1; fiedArry.forEach(function(field) { $(target).bootstrapTable('mergeCells',{index:index, field:field, colspan: colspan, rowspan: count}); }); index += count; } }