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,你能够用它进行多字段排序,好比用在合并相同单元格的场景,在绘制表格前先对数据进行排序,那么最后合并的结果就是把全部相同的数据聚合到一块儿了,而且还将它们合并到一块儿了,起到了一个隐形的过滤查询功能。