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; } }