工作中想用如图的方式去展示数据,虽然网上也有其它人写的相关插件,但是几乎都是一次性请求好数据并且不支持分页,不符合项目需求,所以就自己改了个,尽量避免动原插件的既有功能,当点击行前的折叠图标时,会通过ajax从后台调取数据并插入到表格中。
1、修改 BootstrapTable.prototype.initHeader 函数
var tempClass='';
if(that.options.treeView && column['field']===that.options.treeField){
tempClass=column['class']+' tree-field ';
}else{
tempClass=column['class'];
}
var text = '',
halign = '', // header align style
align = '', // body align style
style = '',
class_ = sprintf(' class="%s"', tempClass),
order = that.options.sortOrder || column.order,
unitWidth = 'px',
width = column.width;
2、修改 BootstrapTable.prototype.initRow 函数
var content=value;
if (that.options.treeView && column.field == that.options.treeField) {
var tempIsLastChild=$.extend(true,[],item.isLastChild);
var indent='',indentCount=0,treeRootLevel,treeMaxLevel,
selfIsLastChild=(tempIsLastChild.pop())?' tree-branch-last':'',
iconStatus=item.isExpand?' tree-expand':' tree-collapse';
// 对参数配置进行校验
if (that.options.treeRootLevel===undefined) {
treeRootLevel=data[0][that.options.treeLevelField]||0;
$.each(data,function(_index,v){
v[that.options.parentId]=v[that.options.parentId]||'';
treeRootLevel=Math.min(treeRootLevel,v[that.options.treeLevelField]);
});
}else{
treeRootLevel=parseInt(that.options.treeRootLevel);
}
// 防止 treeRootLevel 为非数字的情况
treeRootLevel=treeRootLevel||0;
treeMaxLevel=that.options.treeMaxLevel||Infinity;
item[that.options.treeParentLevelField]=item[that.options.treeParentLevelField]||treeRootLevel;
// 结构树的html
indent='';
if(item[that.options.parentId]||that.options.treeRootLevel!==undefined){// 绘制数据前的树结构线
for(var _index=treeRootLevel;_index<=item[that.options.treeParentLevelField];_index++){
indentCount++;
if (tempIsLastChild.shift()) {
indent+='';
}else{
indent+='';
}
}
}
if(item[that.options.treeLevelField]',
id_, class_, style, data_, rowspan_, colspan_, title_),
indent,
content,
''
].join('');
3、修改 BootstrapTable.prototype.initBody 函数
// 在函数头部的循环中为每个节点增加isLastChild属性
for (var i = this.pageFrom - 1; i < this.pageTo; i++) {
var item = data[i];
if (that.options.treeView && data.length>0) {
if (!item.isLastChild) {
item.isLastChild=[];
if (i==this.pageTo-1) {
item.isLastChild.push(true);
}else{
item.isLastChild.push(false);
}
}
}
var tr = this.initRow(item, i, data, trFragments);
hasTr = hasTr || !!tr;
if (tr&&tr!==true) {
trFragments.append(tr);
}
}
this.$body.find('> tr[data-index] > td .tree-icon').off('click').on('click', function (e) {
e.stopPropagation();
var $this = $(this),
$tr = $this.closest('tr'),
index = $tr.data('index'),
row = data[index];
var icon = $(this);
// 给被点击的行数据添加一个isExpand字段,记录它的“展开/折叠”状态
row.isExpand=!row.isExpand;
// 处理展开和折叠事件
if (icon.hasClass('tree-expand')) {
// 梳理需要折叠的tr行号范围,parentId为父节点的Id
var start=index;
if (row.isLastChild[row.isLastChild.length-1]) {
for (var i = index+1; i tr:eq('+start+') .tree-icon').click();
}
}else{
for (var i = index+1; i index; i--) {
data.splice(i,1);
}
} else {
// 展开子节点时,首先通过 getChild 函数获取子节点(这里假设是同步ajax请求,想要异步可适当调整)
var child=that.options.getChild(index, that.options.treeId);
if (child.length>0) {
child[0].isLastChild=true;
}
// 将子节点循环插入到当前节点后面
$.each(child, function (i, v) {
// 设置该行tree-field中的所有辅助线是否是同级最后一个,以便区别样式
v.isLastChild=$.extend(true,[],row.isLastChild);
if (i===0) {
v.isLastChild.push(true);
}else{
v.isLastChild.push(false);
}
if (row[that.options.treeId] == v[that.options.parentId]) {
data.splice(index+1,0,v);
}
});
}
// 重绘页面表格
that.initBody(true);
});
4、iconfont及css样式
增加了少许样式和字体,较简单,详见代码。
三、后记1、目前 getChild 函数获取数据时,还只支持同步请求,后续将改为支持异步;
2、代码及DEMO



