使用FastAdmin快速创建应用管理系统有一段时间了,不得不说在一些中小型应用领域使用起来非常快捷、有效和实用,对于一些需要前期快速验证的项目也会是很好的选择。闲言少叙,以下总结最近一个表格前端效果的实战经验。
FastAdmin使用bootstrap-table作为前端表格的基础组件库,通常列表交互展示已经够用了,包括通用搜索、排序、分页、导出、合并相同行/列等等。最近需要对表头进行冻结,找到了bootstrap-table-fixed-columns组件(也是bootstrap-table作者写的)能实现冻结效果,但带来了其他问题,包括:排序失效、列宽错位、合并行无效等,于是引入该组件的同时,顺便解决了这些问题,并且封装回原js中,使用时可以无忧无虑啦~
一、引入js组件
FastAdmin的前端使用的是RequireJS引入js,因此需按其规则来加载,当然直接在html用原生script方式也能用,但就不那么优雅了,是不是?
1、将js和css文件复制到public/assets/libs/bootstrap-table/dist目录下,我会上传到本文的资源文件中供大家下载。
2、找到public/assets/js/require-backend.js文件,大约在35行左右,配置文件路径。
我有点小强迫症,一定要放在bootstrap-table相关组件一起,如图:
代码放出来方便copy:
'bootstrap-table-fixed-columns': '../libs/bootstrap-table/dist/bootstrap-table-fixed-columns',
90行左右,bootstrap-table-template节点下,配置shim依赖:
'bootstrap-table-fixed-columns': {
deps: ['bootstrap-table','css!../libs/bootstrap-table/dist/bootstrap-table-fixed-columns.css'],
exports: '$.fn.bootstrapTable.defaults'
},
二、使用bootstrap-table-fixed-columns
1、在对应的js文件头部,引入申明
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'bootstrap-table-fixed-columns'], function ($, undefined, Backend, Table, Form) {
2、在table的options中增加冻结表头配置项
table.bootstrapTable({
...
fixedColumns: true,//固定列
fixedNumber:2,//固定前两列
...
});
到此为止效果就出来啦,是不是很简单!
三、扩展说明
1、bootstrap-table-fixed-columns原理
bootstrap-table-fixed-columns实际上是“继承”了bootstrap-table,在一些关键生命周期做了处理,如initHeader、initBody和resetView,增加了冻结列的追加操作。从F12分析看,本质上是在原表格的基础上,“覆盖”了固定的列,当拖动滚动条时,看起来那几列是没有动的,也就是欺骗了眼睛:)
2、完善排序、列宽自动适配
之所以排序失效,就是因为覆盖的表头“遮挡”了原表头,无法响应点击事件了,因此解决的思路自然就是“恢复”原有的事件响应。其他的列宽适配、合并行等类似。以onSort为例:
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_init = BootstrapTable.prototype.init,
_initHeader = BootstrapTable.prototype.initHeader,
_initBody = BootstrapTable.prototype.initBody,
_resetView = BootstrapTable.prototype.resetView,
_onSort = BootstrapTable.prototype.onSort, // 排序时需增加对图标的同步更新
_mergeCells = BootstrapTable.prototype.mergeCells;// 扩展合并表格方法
// 针对base table没有prototype的方法,在这里调用
BootstrapTable.prototype.init = function () {
_init.apply(this, Array.prototype.slice.apply(arguments));
var that = this;
// 数据加载完成时需要对列宽度同步适配
this.$el.on('load-success.bs.table', function () {
that.onLoadSuccess();
});
// 显示/隐藏字段时需要对列宽度同步适配
this.$el.on('column-switch.bs.table', function () {
that.onColumnSwitch();
});
};
.......
BootstrapTable.prototype.onSort = function () {
_onSort.apply(this, Array.prototype.slice.apply(arguments));
if (!this.options.fixedColumns) {
return;
}
var name = this.options.sortName;
var order = this.options.sortOrder;
// 解决冻结列排序图标同步变化效果
$(".fixed-table-header-columns").find("th[data-field]").find("div.sortable").removeClass("asc desc")
$(".fixed-table-header-columns").find("th[data-field=" + name + "]").find("div.sortable").removeClass("asc desc").addClass(order);
};
// 其他代码见资源
3、合并相同行
bootstrap-table提供了mergeCells方法实现合并,但具体要合并哪些cell,需要我们来确定,以下引用了网上的一段代码,在onLoadSuccess和onColumnSwitch(显示/隐藏字段)时调用,以实现行合并:
function mergeTable(tableId, fieldname) {
var rows = $(tableId).bootstrapTable('getData');
var rowspan = 0;
var index = 0;
var last_value = '';
$.each(rows, function (i, row) {
if (i == 0) {
last_value = row[fieldname];
rowspan = 1;
index = i;
} else {
if (last_value === row[fieldname]) {
rowspan++;
}
else {
$(tableId).bootstrapTable('mergeCells', { index: index, field: fieldname, colspan: 1, rowspan: rowspan });
last_value = row[fieldname];
rowspan = 1;
index = i;
}
if (i == (rows.length - 1)) {
$(tableId).bootstrapTable('mergeCells', { index: index, field: fieldname, colspan: 1, rowspan: rowspan });
}
}
});
}
到此,完美解决冻结表格的问题。
资源文件下载地址:https://download.csdn.net/download/paulluo0739/12230374