Bootstrap-table 官方提供了合併單元格方法 mergeCells,它根據四個參數能夠合併任意個單元格,咱們要作的只是告訴它怎麼合併。git
要合併同一列相同的單元格,無非兩種辦法,一種是一邊遍歷一邊合併,遍歷完了再合併。這裏採用第二種辦法,這裏不須要遍歷全部數據,由於用戶只能看到當前頁的數據,因此只遍歷當前頁的數據更省時間。github
下面是我實現的獲取合併信息算法,最終返回的是一個哈希表,好比下面的這個表格,若是要對「性別」這一列進行合併,很明顯前面兩個「男」須要合併成一個單元格,再去看下 Bootstrap-table 提供的 API,它須要的是從哪一個單元格開始,合併多少個單元格,也就是它須要的是兩個數值類型的參數。算法
姓名 | 性別 | 年齡 |
---|---|---|
張三 | 男 | 23 |
李四 | 男 | 19 |
王二 | 女 | 20 |
麻子 | 男 | 21 |
因此我把哈希表設置爲,鍵存的是索引,值存的是從這個索引開始後面連續有多少個和它同樣的單元格,那麼上述表格性別這一列所獲得的合併信息哈希表就爲:typescript
{
0: 2,
2: 1,
3: 1
}
複製代碼
下面算法很簡單,使用兩個指針遍歷指定的列,若是兩個指針所指向的數據相同,那麼就將鍵所對應的值進行加一操做,整個方法只會對該列數據遍歷一邊,因此時間複雜度爲 O(n)。bootstrap
let getMergeMap = function (data, index: number) {
let preMergeMap = {};
// 第 0 項爲表頭,索引從 2 開始爲了防止數組越界
for (let i = 2; i < data.length; i++) {
let preText = $(data[i-1]).find('td')[index].innerText;
let curText = $(data[i]).find('td')[index].innerText;
let key = i - 2;
preMergeMap[key] = 1;
while ((preText == curText) && (i < data.length-1)) {
preMergeMap[key] = parseInt(preMergeMap[key]) + 1;
i++;
preText = $(data[i - 1]).find('td')[index].innerText;
curText = $(data[i]).find('td')[index].innerText;
}
// while循環跳出後,數組最後一項沒有判斷
if (preText == curText) {
preMergeMap[key] = parseInt(preMergeMap[key]) + 1;
}
}
return preMergeMap;
}
複製代碼
上述算法獲得了單列數據的合併信息,下一步就是按照這個信息進行相同單元格的合併了,所以封裝了下面的方法按照指定哈希表進行合併。api
let mergeCells = function (preMergeMap: Object, target, fieldName: string) {
for (let prop in preMergeMap) {
let count = preMergeMap[prop];
target.bootstrapTable('mergeCells', { index: parseInt(prop), field: fieldName, rowspan: count });
}
}
複製代碼
到目前爲止,咱們實現的都只是對單列數據進行合併,要實現對多列數據進行合併,那麼只須要對全部列都進行相同的操做便可。數組
export let mergeCellsByFields = function (data: Object[], target, fields) {
for (let i = 0; i < fields.length; i++) {
let field = fields[i];
// 保證 field 與 i 是相對應的
let preMergeMap = getMergeMap(data, i);
let table = target.bootstrapTable();
mergeCells(preMergeMap, table, field);
}
}
複製代碼
由於我在程序中作了一點處理,保證了fields
中每一個值得索引與對應表頭的索引是同樣的,所以不須要額外傳入索引信息。簡單來講就是我所實現的表格會根據fields
的順序,實現列之間的動態排序。你須要注意的是這一點極可能和你不同。bash
到如今已經可以合併全部的列了,查看 Bootstrap-table 的配置信息發現,它有個屬性是 onPostBody 它會在 table body 加載完成是觸發,因此把這個屬性配置成咱們的合併單元格方法便可。post
// groups 爲要合併的哪些列
onPostBody: function () {
mergeCellsByFields($('#table' + ' tr'), $('#table'), groups);
}
複製代碼
再說一點不太相關的,我實現的是讓用戶能夠本身選能夠合併多少列,即用了一個可多選的下拉列表框供用戶選擇,根據用戶選擇的數量去合併,因此傳入了一個groups
參數。ui
最後推薦一個排序插件 thenBy,你能夠用它進行多字段排序,好比用在合併相同單元格的場景,在繪製表格前先對數據進行排序,那麼最後合併的結果就是把全部相同的數據聚合到一塊兒了,而且還將它們合併到一塊兒了,起到了一個隱形的過濾查詢功能。