Bootstrap-table 合并相同单元格

    Bootstrap-table 官方提供了合并单元格方法 mergeCells,它根据四个参数可以合并任意个单元格,我们要做的只是告诉它怎么合并。

    要合并同一列相同的单元格,无非两种办法,一种是一边遍历一边合并,遍历完了再合并。这里采用第二种办法,这里不需要遍历所有数据,因为用户只能看到当前页的数据,所以只遍历当前页的数据更省时间。

    下面是我实现的获取合并信息算法,最终返回的是一个哈希表,比如下面的这个表格,如果要对「性别」这一列进行合并,很明显前面两个“男”需要合并成一个单元格,再去看下 Bootstrap-table 提供的 API,它需要的是从哪个单元格开始,合并多少个单元格,也就是它需要的是两个数值类型的参数。

姓名性别年龄
张三23
李四19
王二20
麻子21

    所以我把哈希表设置为,键存的是索引,值存的是从这个索引开始后面连续有多少个和它一样的单元格,那么上述表格性别这一列所得到的合并信息哈希表就为:

{
    0: 2,
    2: 1,
    3: 1
}
复制代码

    下面算法很简单,使用两个指针遍历指定的列,如果两个指针所指向的数据相同,那么就将键所对应的值进行加一操作,整个方法只会对该列数据遍历一边,所以时间复杂度为 O(n)。

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;
}
复制代码

    上述算法得到了单列数据的合并信息,下一步就是按照这个信息进行相同单元格的合并了,因此封装了下面的方法按照指定哈希表进行合并。

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的顺序,实现列之间的动态排序。你需要注意的是这一点很可能和你不一样。

    到现在已经能够合并所有的列了,查看 Bootstrap-table 的配置信息发现,它有个属性是 onPostBody 它会在 table body 加载完成是触发,所以把这个属性配置成我们的合并单元格方法即可。

// groups 为要合并的哪些列
onPostBody: function () {
        mergeCellsByFields($('#table' + ' tr'), $('#table'), groups);
      }
复制代码

    再说一点不太相关的,我实现的是让用户可以自己选可以合并多少列,即用了一个可多选的下拉列表框供用户选择,根据用户选择的数量去合并,所以传入了一个groups参数。

    最后推荐一个排序插件 thenBy,你可以用它进行多字段排序,比如用在合并相同单元格的场景,在绘制表格前先对数据进行排序,那么最后合并的结果就是把所有相同的数据聚合到一起了,并且还将它们合并到一起了,起到了一个隐形的过滤查询功能。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
合并单元,需要使用 `react-bootstrap-table-next` 中的 `rowSpan` 和 `colSpan` 属性。这些属性可以在 `columns` 对象中定义,用于指定表中每个单元应该跨越的行和列的数量。 具体的实现步骤如下: 1. 在 `columns` 对象中定义需要合并单元的列,为其添加 `rowSpan` 和 `colSpan` 属性。 2. 在 `data` 数组中为需要合并单元的行添加相应的属性值,这些属性值将在表渲染时被引用。 下面是一个例子: ```javascript import BootstrapTable from 'react-bootstrap-table-next'; import 'react-bootstrap-table-next/dist/react-bootstrap-table2.min.css'; const columns = [ { dataField: 'id', text: 'ID', }, { dataField: 'name', text: 'Name', }, { dataField: 'age', text: 'Age', }, { dataField: 'gender', text: 'Gender', rowSpan: 2, // 跨越两行 }, { dataField: 'location', text: 'Location', colSpan: 2, // 跨越两列 }, { dataField: 'address', text: 'Address', hidden: true, // 隐藏该列 }, { dataField: 'city', text: 'City', }, { dataField: 'state', text: 'State', }, ]; const data = [ { id: 1, name: 'John', age: 30, gender: 'Male', location: 'New York', address: '123 Main St', city: 'New York', state: 'NY', }, { id: 2, name: 'Jane', age: 25, gender: 'Female', location: 'San Francisco', address: '456 Elm St', city: 'San Francisco', state: 'CA', }, ]; <BootstrapTable keyField='id' data={ data } columns={ columns }/> ``` 在上面的例子中,表中的 `Gender` 列跨越了两行,`Location` 列跨越了两列。注意,在定义了 `colSpan` 属性的列后面应该添加相应数量的列来占据跨度。 希望这可以帮助你实现合并单元的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值