Bootstrap-table 合併相同單元格

    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,你能夠用它進行多字段排序,好比用在合併相同單元格的場景,在繪製表格前先對數據進行排序,那麼最後合併的結果就是把全部相同的數據聚合到一塊兒了,而且還將它們合併到一塊兒了,起到了一個隱形的過濾查詢功能。

相關文章
相關標籤/搜索