CSS实现树形结构 + js加载数据

  看到一款树形结构,比较喜欢它的样式,就参照它的外观自己做了一个,练习一下CSS。

  做出来的效果如下:

  • 拉莫小学
    • 一年级
      • 一班
      • 二班
    • 二年级
    • 三年级
      • 一班
      • 二班
      • 三班

树的dom结构:

1<div class="tree"> 2 <ul> 3 <li> 4 <span><i class="fa fa-minus-circle"></i>拉莫小学</span> 5 <ul> 6 <li> 7 <span><i class="fa fa-minus-circle"></i>一年级</span> 8 <ul> 9 <li><span>一班</span></li><li><span>二班</span></li> 10 </ul> 11 </li> 12 <li> 13 <span>二年级</span> 14 </li> 15 <li> 16 <span><i class="fa fa-minus-circle"></i>三年级</span> 17 <ul> 18 <li><span>一班</span></li> 19 <li><span>二班</span></li> 20 <li><span>三班</span></li> 21 </ul> 22 </li> 23 </ul> 24 </li> 25 </ul> 26</div>

CSS代码:

1/** tree.css zyj 2018.4.21 */ 2ul,li{list-style-type:none;} 3.tree{display:block;position:relative;padding:5px 15px;} 4.tree span{display:inline-block;box-sizing:border-box;height:30px;line-height:28px;min-width:60px;text-align:center;color:#888;border:1px solid #ddd;border-radius:5px;padding:0 8px;} 5.tree ul{position:relative;padding-left:60px;margin:0;} 6.tree ul>li{position:relative;padding:5px 0;} 7.tree>ul{padding:0;margin:0;} 8/** 水平方向连线 */ 9.tree>ul ul>li:after{content:' ';position:absolute;top:20px;left:-45px;width:45px;border:none;border-top:1px solid #ddd;} 10/** 垂直方向连线 */ 11.tree ul>li:not(:last-child):before{content:' ';position:absolute;top:0;left:-45px;height:100%;border:none;border-left:1px solid #ddd;} 12.tree ul>li:last-child:before{content:' ';position:absolute;top:0;left:-45px;height:20px;border:none;border-left:1px solid #ddd;} 13/** 控制鼠标移上去的颜色 */ 14.tree span:hover, .tree span:hover+ul span{color:#fff;background-color:orange;} 15.tree span:hover, .tree span:hover+ul span, .tree span:hover+ul li:before, .tree span:hover+ul li:after{border-color:orange;} 16/** 折叠图标 */ 17.tree .fa:before{margin-right:5px;} 18.tree .fa-minus-circle, .tree .fa-plus-circle{cursor:pointer;}

里面引的fontawesome图标没法加载进来,导致折叠按钮显示不出,下面是原始树状图的截图:

数据是我用JS加载的,写了个加载数据的tree.js文件,源码如下:

1/** tree.js zyj 2018.4.22 */ 2(function(name){ 3 var tree, outer, defaultDateFormat; 4 5 outer = { 6 setData : setData, 7 }; 8 9 defaultDateFormat = { 10 unfold : true, 11 name : 'name', 12 childName : 'children' 13 }; 14 15 function getDataFormat(dataFormat){ 16 var index; 17 if(!dataFormat){ 18 return defaultDateFormat; 19 } 20 for(index in defaultDateFormat){ 21 dataFormat[index] = typeof dataFormat[index] == 'undefined'? defaultDateFormat[index] : dataFormat[index]; 22 } 23 return dataFormat 24 } 25 26 function initTreeJs(name){ 27 var tree; 28 if(checkTreeNameUsed(name)){return;} 29 window[name] = outer; 30 initFoldIcon($('.tree')); 31 } 32 33 function checkTreeNameUsed(name){ 34 if(window[name]){ 35 console.error("The window object name [" + name + "] has been used, tree.js can't be loaded! You can try another name." ); 36 return true; 37 } 38 return false; 39 } 40 41 function initFoldIcon(target){ 42 target.off('click', 'span>i.fa').on('click', 'span>i.fa', function(e){ 43 var ele = $(e.target); 44 if(ele.hasClass('fa-minus-circle')){ 45 ele.removeClass('fa-minus-circle').addClass('fa-plus-circle').parent().next('ul').hide(200); 46 }else if(ele.hasClass('fa-plus-circle')){ 47 ele.removeClass('fa-plus-circle').addClass('fa-minus-circle').parent().next('ul').show(200); 48 } 49 }) 50 } 51 52 function getJqueryObjectBySelector(selector){ 53 var ele = $(selector); 54 if(typeof selector != 'string'){ 55 console.error("The first parameter jquery selector [" + selector + "] must be a string!" ); 56 return; 57 } 58 if(!ele.hasClass('tree')){ 59 ele = ele.find('.tree'); 60 } 61 if(ele.length != 1){ 62 console.error("The selector [" + selector + "] expect only one element!" ); 63 return; 64 } 65 return ele; 66 } 67 68 function setData(selector, data, dataFormat){ 69 var ele = getJqueryObjectBySelector(selector); 70 if(!ele){return;} 71 if(!data){return;} 72 if(!data.length){ 73 data = [data]; 74 } 75 dataFormat = getDataFormat(dataFormat); 76 dataFormat.topElement = true; 77 ele.empty().append(getTreeList(data, dataFormat)); 78 initFoldIcon(ele); 79 } 80 81 function getTreeList(data, dataFormat){ 82 var i, single, name, children, childDataFormat, 83 array = []; 84 childDataFormat = dataFormat.child || dataFormat; 85 if(dataFormat.unfold){ 86 array.push('<ul>'); 87 }else if(dataFormat.topElement){ 88 dataFormat.topElement = false; 89 array.push('<ul>'); 90 }else{ 91 array.push('<ul style="display:none;">'); 92 } 93 for(i=0; i<data.length; i++){ 94 single = data[i]; 95 if(typeof dataFormat.name == 'function'){ 96 name = dataFormat.name(single); 97 }else if(typeof dataFormat.name == 'string'){ 98 name = single[dataFormat.name]; 99 }else{ 100 name = single['name']; 101 } 102 if(typeof dataFormat.childName == 'string'){ 103 children = single[dataFormat.childName]; 104 }else{ 105 children = single['children']; 106 } 107 array.push('<li>'); 108 array.push('<span>'); 109 if(children && children.length > 0){ 110 if(dataFormat.unfold){ 111 array.push('<i class="fa fa-minus-circle"></i>'); 112 }else{ 113 array.push('<i class="fa fa-plus-circle"></i>'); 114 } 115 array.push(name); 116 array.push('</span>'); 117 array.push(getTreeList(children, childDataFormat)); 118 }else{ 119 array.push(name); 120 array.push('</span>'); 121 } 122 array.push('</li>'); 123 } 124 array.push('</ul>'); 125 return array.join(''); 126 } 127 128 initTreeJs(name); 129}('tree'))

偷懒没写注释,tree.js中目前只写了一个对外的接口 tree.setData(selector, data, dataFormat) 。参数selector是jQuery选择器,data是数据,dataFormat是数据格式。

比如加载上图的数据:

1var dataTest = { 2name:'拉莫小学', 3children:[ 4 { 5 name:'一年级', 6 children:[ 7 {name:'一班'}, 8 {name:'二班'} 9 ] 10 }, 11 { 12 name:'二年级' 13 }, 14 { 15 name:'三年级', 16 children:[ 17 {name:'一班'}, 18 {name:'二班'}, 19 {name:'三班'} 20 ] 21 } 22] 23}; 24 25tree.setData('.tree', dataTest);

由于后台加载的数据不一定是按照{name:'*', children:[{name:'*'},...]}这种结构,所以留了dataFormat参数,自己去定义数据格式。

简单举个例子,假如后台数据格式是

1var data ={ 2 id : '1', 3 title : '百度', 4 url : 'http://www.baidu.com', 5 subWeb : 6 [ 7 { 8 id : '2', 9 title : '百度新闻', 10 url : 'http://news.baidu.com' 11 }, 12 { 13 id : '3', 14 title : '百度知道', 15 url : 'http://zhidao.baidu.com' 16 }, 17 { 18 id : '4', 19 title : '百度图片', 20 url : 'http://image.baidu.com' 21 }, 22 ] 23}

那么dataFormat可以定义为

1var dataFormat = 2{ 3 name : function(data){ 4 return '<a href="' + data.url + '">' + data.title + '</a>'; 5 }, 6 childName : 'subWeb' 7}

至于效果,读者自己去试咯。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )