赞
踩
树表格,表格树,就是可以像菜单一样折叠展开的表格。对于具有上下级关系的数据,用表格树展示颇为直观方便。
最近对 ztree、ligerGrid、dataTables三个插件进行了一番研究。主要对比了它们对于各列各行数据的样式、逻辑的可控程度、灵活程度。
首先声明一下:在本文中,能进行伸缩有层级关系的列称为主列,其他称为从列,如下图
本文没有列出全部代码,只有部分片段,需要完整代码可前往https://gitee.com/willbebetter/table_tree_demo免费下载
样式比较丑,如果真要用的话,相信各位朋友可以写出自己满意的样式
下面开始正题
先看 demo 吧
1)可以给主列加样式,需设置 nameIsHTML 为 true,并且我试了 < a > 和 < div >标签是会解析出问题的,从列可以用任意标签。
2)因为主列是直接解析数据展现出来的,我没找到可以控制主列的显示逻辑的方法,比如可写个判断,主列的地区全部显示黑色,但是企业显示蓝色(这种效果可以通过在每个对象name属性加上一个class来控制)。从列是可以的,比如本例中判断电话是否为空,分别处理。
3)主列也没办法单独绑定click事件,可以用回调函数 onClick,但是这样的话,绑定的是整行,无论点该行的哪里,都会触发该事件。从列可以通过嵌入的html给单独的列进行绑定。
初始化表头
//初始化列表
zTreeNodes = data;
//初始化树
var treeObj = $.fn.zTree.init($("#dataTree"), setting, zTreeNodes);
// treeObj.expandAll(true); //展开/折叠所有节点
//添加表头
var li_head = ' <li class="head"><a><div class="diy">企业名称</div><div class="diy">企业地址</div><div class="diy">联系人</div>' +
'<div class="diy">联系方式</div><div class="diy">操作</div></a></li>';
var rows = $("#dataTree").find('li');
if (rows.length > 0) {
rows.eq(0).before(li_head)
} else {
$("#dataTree").append(li_head);
$("#dataTree").append('<li ><div style="text-align: center;line-height: 30px;" >无符合条件数据</div></li>')
}
参数设置
var zTreeNodes; var setting = { view: { showLine: false, showIcon: false, nameIsHTML: true, //为了给主列搞点花样,把这个属性找出来了,功能如同属性名,把主列属性值解析为html,默认为false //但是不能使用<div>和<a>标签,会和插件冲突。我测试中用的是<span>,但是好像不能用class和id绑定事件 addDiyDom: addDiyDom //自定义节点显示方式 }, data: { simpleData: { enable: true }, key: { name: "name", //指定主列的属性,默认为 name url: "baiduUrl" //指定跳转路径属性,单击触发,单机该行的任意单元格都可触发,不管有无数据;默认是对象中的url属性 } }, callback: { //onClick: dblClick onDblClick: dblClick //这里的单击和双击都是整行生效的,该行的任意地方都可触发,不管有无数据; } }; /** * 自定义DOM节点 */ function addDiyDom(treeId, treeNode) { var spaceWidth = 15; var liObj = $("#" + treeNode.tId); var aObj = $("#" + treeNode.tId + "_a"); var switchObj = $("#" + treeNode.tId + "_switch"); var icoObj = $("#" + treeNode.tId + "_ico"); var spanObj = $("#" + treeNode.tId + "_span"); aObj.attr('title', ''); aObj.append('<div class="diy swich"></div>'); var div = $(liObj).find('div').eq(0); switchObj.remove(); spanObj.remove(); icoObj.remove(); div.append(switchObj); div.append(spanObj); var spaceStr = "<span style='height:1px;display: inline-block;width:" + (spaceWidth * treeNode.level) + "px'></span>"; switchObj.before(spaceStr); //这里自定义的都是 从列的样式和逻辑, var editStr = ''; editStr += '<div class="diy"><a href="javascript:void();" οnclick="alert(1111);">' + (treeNode.address == null ? ' ' : treeNode.address) + '</a></div>'; editStr += '<div class="diy">' + (treeNode.headMan == null ? ' ' : treeNode.headMan ) + '</div>'; if(treeNode.tel == null){ editStr += '<div class="diy"> </div>'; }else{ editStr += '<div class="diy"><input type="button" value="'+ treeNode.tel +'" class="btnstyle" οnclick="btntest()" /></div>'; } editStr += '<div class="diy">' + formatHandle(treeNode) + '</div>'; aObj.append(editStr); }
数据格式
var data = [ { name: '北京市', isArea: true, children: [ { name: '海淀区', isArea: true, children: [ { isArea: false, name: '北京海淀科技有限公司', address:"北京海淀xx路1号", headMan:"张三", tel:"15910101234" }, { isArea: false, name: '北京海淀软件测试有限公司', address:"北京海淀xx路10号", headMan:"李四", tel:"15209094321" } ] }, { name: '西城区', isArea: true, children: [ { isArea: false, name: '北京西城科技有限公司', address:"北京西城xx路1号", headMan:"王五", tel:"13511112222" } ] }, { name: '丰台区', isArea: true} ] }, { name: '广东省', isArea: true, children: [ { name: '广州市', isArea: true, children: [ //使用 <a> 标签,这个信息到这个表格的外面了 { isArea: false, name: "<a href='https://www.baidu.com'>广东广州科技有限公司</a>", address:"广东广州xx路1号", headMan:"赵六", tel:"13622226666" } ] }, { name: '深圳市', isArea: true } ] }, //下面是没有 children 属性的数据格式,需要 id 和 pid {"id":"jxs","pId":"onull","name":"<span class='namestyle'>江西省</span>","tel":null,"open":true,"isArea":true}, {"id":"ncs","pId":"jxs","name":"南昌市","tel":null,"open":true,"isArea":true}, {"id":"com1","pId":"ncs","name":"<span id='namestyle'>江西南昌科技有限公司</span>","address":"江西南昌xx路101号","headMan":"xiao","tel":"15812345678","isArea":false}, {"id":"gzs","pId":"jxs","name":"赣州市","tel":null,"isArea":true,"baiduUrl":"https://www.baidu.com"}, // name 用了 <div> 标签,该行直接不显示了 {"id":"hns","pId":"onull","name":"<div>湖南省</div>","tel":null,"isArea":true} ];
1)不管主列还是从列,甚至最前面的图标,都是单独的列,可以进行样式和逻辑的控制,绑定事件也很轻松,相当灵活。
2)有一个不太好的地方是,因为图标是单独的一列,显得与主列名称相隔太远,无论层级多么深入,最里层的图标都会在最外层主列名称的左边,显得很不自然。
var dataTable; $(function() { dataTable = $('#treetable').DataTable( { /** l - Length changing 改变每页显示多少条数据的控件 f - Filtering input 即时搜索框控件 t - The Table 表格本身 i - Information 表格相关信息控件 p - Pagination 分页控件 r - processing 加载等待显示信息 **/ "dom" : "tr", "ordering" : false, //禁用排序 "processing" : true, "serverSide" : true, "ajax" : { "url" : "../static/json/dataTablesData.json", }, 'treeGrid' : { 'left' : 20, //主列的缩进 'expandAll' : true, //是否默认展开 true 是 //'expandIcon': '<span> + </span>', //'collapseIcon': '<span> - </span>' // 注意:包裹图标标签的 <span> 标签不能少,否则子节点缩进格式会有问题 'expandIcon' : '<span><img src="../static/css/img/diy/1_close.png" /></span>', 'collapseIcon' : '<span><img src="../static/css/img/diy/1_open.png" /></span>' }, "columns" : [ { className : 'treegrid-control', data : function(item) { if (item.children != null&& item.children.length > 0) { return '<span><img src="../static/css/img/diy/1_close.png" /></span>'; } return ''; } }, // 表格的每一列样式都可以用 className 来渲染 // 每一列的数据表现形式、逻辑都可用函数实现,非常灵活 // { // "data" : "name" // }, { className : 'diyclass', data : function(item) { if (item.address != null) { return "<a href='https://www.baidu.com'>"+item.name+"</a>"; } return item.name; } }, { //"data" : "<a href='https://www.baidu.com'>address</a>" //此写法错误,得用函数 "data" : "address" }, {"data": "headMan"}, { className : 'diyclass', data : function(item) { if (item.tel != null) { return "<input type='button' value='"+item.tel+"' class='btnstyle'/>"; } return "<a href='javascript:btntest();' >click</a>"; } } ], "columnDefs" : [ { "defaultContent" : "", "targets" : "_all" } ] }); }); function btntest(){ alert("电话获取中。。。"); }
这个我感觉也很不错,主列从列都可以通过自定义的函数来控制样式和逻辑,非常灵活。有一个问题我没解决的是,怎么让表头左对齐?
function f_renderDetail(rowdata, index, value) { if (rowdata.isArea) { return value; } else { return "<a href='https://www.baidu.com' target='_blank'>"+value+"</a>"; } } function f_renderClick(rowdata, index, value) { if (value != null) { return "<span class='clickStyle' οnclick='clickTel(\""+rowdata.id+"\",\""+value+"\")'>"+value+"</span>"; } else { return value; } } function clickTel(id,tel){ alert("这是"+id+"的电话:"+tel); } var manager; $(function() { // 不管是主列还是从列,都可以用 render 属性自定义样式和逻辑 manager = $("#maingrid").ligerGrid({ columns : [ { display : '企业', name : 'id', width : '25%', align : 'left', render : f_renderDetail }, { display : '地址', name : 'address', width : '25%', align : 'left' }, { display : '联系人', name : 'headMan', width : '25%', align : 'left' }, { display : '电话', name : 'tel', width : '25%', align : 'left', render : f_renderClick //自定义样式、显示逻辑等 } ], width : '80%', // height : '97%', // pageSizeOptions: [5, 10, 15, 20], data : TreeData, alternatingRow : false, tree : { columnName : 'id' //指定主列的属性 }, onDblClickRow : function (data, rowindex, rowobj) { if(data.isArea){ alert("这是地区"); }else{ alert("这是企业"); } } // enabledEdit: true }); manager.bind('beforeEdit', function(e) { if (this.hasChildren(e.record)) return false; else return true; }); });
最后,感谢以下博主
https://blog.csdn.net/duqian42707/article/details/52886220
https://blog.csdn.net/lhmyy521125/article/details/86528502
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。