树表格之 ztree、ligerGrid、dataTables

树表格,表格树,就是可以像菜单一样折叠展开的表格。对于具有上下级关系的数据,用表格树展示颇为直观方便。
最近对 ztree、ligerGrid、dataTables三个插件进行了一番研究。主要对比了它们对于各列各行数据的样式、逻辑的可控程度、灵活程度。
首先声明一下:在本文中,能进行伸缩有层级关系的列称为主列,其他称为从列,如下图
在这里插入图片描述
本文没有列出全部代码,只有部分片段,需要完整代码可前往https://gitee.com/willbebetter/table_tree_demo免费下载
样式比较丑,如果真要用的话,相信各位朋友可以写出自己满意的样式
下面开始正题

ztree

先看 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 ? '&nbsp;' : treeNode.address) + '</a></div>';
        editStr += '<div class="diy">' + (treeNode.headMan == null ? '&nbsp;' : treeNode.headMan ) + '</div>';
        if(treeNode.tel == null){
    
    
	        editStr += '<div class="diy">&nbsp;</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}
         	];

dataTables

在这里插入图片描述
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("电话获取中。。。");
		}

ligerGrid

在这里插入图片描述这个我感觉也很不错,主列从列都可以通过自定义的函数来控制样式和逻辑,非常灵活。有一个问题我没解决的是,怎么让表头左对齐?

	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

猜你喜欢

转载自blog.csdn.net/Alias_fa/article/details/99483198