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

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

做出来的效果如下:

ul,li { list-style-type: none }
.tree { display: block; position: relative; padding: 5px 15px }
.tree span { display: inline-block; height: 30px; line-height: 28px; min-width: 60px; text-align: center; color: #888; border: 1px solid #ddd; padding: 0 8px }
.tree ul { position: relative; padding-left: 60px; margin: 0 }
.tree ul>li { position: relative; padding: 5px 0 }
.tree>ul { padding: 0; margin: 0 }
.tree>ul ul>li::after { content: " "; position: absolute; top: 20px; left: -45px; width: 45px; border: none; border-top: 1px solid #ddd }
.tree ul>li:not(:last-child)::before { content: " "; position: absolute; top: 0; left: -45px; height: 100%; border: none; border-left: 1px solid #ddd }
.tree ul>li:last-child::before { content: " "; position: absolute; top: 0; left: -45px; height: 20px; border: none; border-left: 1px solid #ddd }
.tree span:hover,.tree span:hover+ul span { color: #fff; background-color: orange }
.tree span:hover,.tree span:hover+ul span,.tree span:hover+ul li::before,.tree span:hover+ul li::after { border-color: orange }
.tree .fa::before { margin-right: 5px }
.tree .fa-minus-circle,.tree .fa-plus-circle { cursor: pointer }

  • 拉莫小学

    • 一年级

      • 一班
      • 二班
    • 二年级
    • 三年级
      • 一班
      • 二班
      • 三班

树的dom结构:

<div class="tree">
    <ul>
        <li>
            <span><i class="fa fa-minus-circle"></i>拉莫小学</span>
            <ul>
                <li>
                    <span><i class="fa fa-minus-circle"></i>一年级</span>
                    <ul>
                        <li><span>一班</span></li><li><span>二班</span></li>
                    </ul>
                </li>
                <li>
                    <span>二年级</span>
                </li>
                <li>
                    <span><i class="fa fa-minus-circle"></i>三年级</span>
                    <ul>
                        <li><span>一班</span></li>
                        <li><span>二班</span></li>
                        <li><span>三班</span></li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
</div>

CSS代码:

/** tree.css zyj 2018.4.21 */
ul,li{list-style-type:none;}
.tree{display:block;position:relative;padding:5px 15px;}
.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;}
.tree ul{position:relative;padding-left:60px;margin:0;}
.tree ul>li{position:relative;padding:5px 0;}
.tree>ul{padding:0;margin:0;}
/** 水平方向连线 */
.tree>ul ul>li:after{content:‘ ‘;position:absolute;top:20px;left:-45px;width:45px;border:none;border-top:1px solid #ddd;}
/** 垂直方向连线 */
.tree ul>li:not(:last-child):before{content:‘ ‘;position:absolute;top:0;left:-45px;height:100%;border:none;border-left:1px solid #ddd;}
.tree ul>li:last-child:before{content:‘ ‘;position:absolute;top:0;left:-45px;height:20px;border:none;border-left:1px solid #ddd;}
/** 控制鼠标移上去的颜色 */
.tree span:hover, .tree span:hover+ul span{color:#fff;background-color:orange;}
.tree span:hover, .tree span:hover+ul span, .tree span:hover+ul li:before, .tree span:hover+ul li:after{border-color:orange;}
/** 折叠图标 */
.tree .fa:before{margin-right:5px;}
.tree .fa-minus-circle, .tree .fa-plus-circle{cursor:pointer;}

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

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

/** tree.js zyj 2018.4.22 */
(function(name){
    var tree, outer, defaultDateFormat;

    outer = {
        setData : setData,
    };

    defaultDateFormat = {
            unfold : true,
            name : ‘name‘,
            childName : ‘children‘
    };

    function getDataFormat(dataFormat){
        var index;
        if(!dataFormat){
            return defaultDateFormat;
        }
        for(index in defaultDateFormat){
            dataFormat[index] = typeof dataFormat[index] == ‘undefined‘? defaultDateFormat[index] : dataFormat[index];
        }
        return dataFormat
    }

    function initTreeJs(name){
        var tree;
        if(checkTreeNameUsed(name)){return;}
        window[name] = outer;
        initFoldIcon($(‘.tree‘));
    }

    function checkTreeNameUsed(name){
        if(window[name]){
            console.error("The window object name [" + name + "] has been used, tree.js can‘t be loaded! You can try another name." );
            return true;
        }
        return false;
    }

    function initFoldIcon(target){
        target.off(‘click‘, ‘span>i.fa‘).on(‘click‘, ‘span>i.fa‘, function(e){
            var ele = $(e.target);
            if(ele.hasClass(‘fa-minus-circle‘)){
                ele.removeClass(‘fa-minus-circle‘).addClass(‘fa-plus-circle‘).parent().next(‘ul‘).hide(200);
            }else if(ele.hasClass(‘fa-plus-circle‘)){
                ele.removeClass(‘fa-plus-circle‘).addClass(‘fa-minus-circle‘).parent().next(‘ul‘).show(200);
            }
        })
    }

    function getJqueryObjectBySelector(selector){
        var ele = $(selector);
        if(typeof selector != ‘string‘){
            console.error("The first parameter jquery selector [" + selector +  "] must be a string!" );
            return;
        }
        if(!ele.hasClass(‘tree‘)){
            ele = ele.find(‘.tree‘);
        }
        if(ele.length != 1){
            console.error("The selector [" + selector +  "] expect only one element!" );
            return;
        }
        return ele;
    }

    function setData(selector, data, dataFormat){
        var ele = getJqueryObjectBySelector(selector);
        if(!ele){return;}
        if(!data){return;}
        if(!data.length){
            data = [data];
        }
        dataFormat = getDataFormat(dataFormat);
        dataFormat.topElement = true;
        ele.empty().append(getTreeList(data, dataFormat));
        initFoldIcon(ele);
    }

    function getTreeList(data, dataFormat){
        var i, single, name, children, childDataFormat,
            array = [];
        childDataFormat = dataFormat.child || dataFormat;
        if(dataFormat.unfold){
            array.push(‘<ul>‘);
        }else if(dataFormat.topElement){
            dataFormat.topElement = false;
            array.push(‘<ul>‘);
        }else{
            array.push(‘<ul style="display:none;">‘);
        }
        for(i=0; i<data.length; i++){
            single = data[i];
            if(typeof dataFormat.name == ‘function‘){
                name = dataFormat.name(single);
            }else if(typeof dataFormat.name == ‘string‘){
                name = single[dataFormat.name];
            }else{
                name = single[‘name‘];
            }
            if(typeof dataFormat.childName == ‘string‘){
                children = single[dataFormat.childName];
            }else{
                children = single[‘children‘];
            }
            array.push(‘<li>‘);
            array.push(‘<span>‘);
            if(children && children.length > 0){
                if(dataFormat.unfold){
                    array.push(‘<i class="fa fa-minus-circle"></i>‘);
                }else{
                    array.push(‘<i class="fa fa-plus-circle"></i>‘);
                }
                array.push(name);
                array.push(‘</span>‘);
                array.push(getTreeList(children, childDataFormat));
            }else{
                array.push(name);
                array.push(‘</span>‘);
            }
            array.push(‘</li>‘);
        }
        array.push(‘</ul>‘);
        return array.join(‘‘);
    }

    initTreeJs(name);
}(‘tree‘))

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

比如加载上图的数据:

var dataTest = {
name:‘拉莫小学‘,
children:[
   {
       name:‘一年级‘,
       children:[
           {name:‘一班‘},
           {name:‘二班‘}
       ]
   },
   {
       name:‘二年级‘
   },
   {
       name:‘三年级‘,
       children:[
           {name:‘一班‘},
           {name:‘二班‘},
           {name:‘三班‘}
       ]
   }
]
};

tree.setData(‘.tree‘, dataTest);

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

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

var data ={
    id : ‘1‘,
    title : ‘百度‘,
    url : ‘http://www.baidu.com‘,
    subWeb :
    [
         {
             id : ‘2‘,
             title : ‘百度新闻‘,
             url : ‘http://news.baidu.com‘
         },
         {
             id : ‘3‘,
             title : ‘百度知道‘,
             url : ‘http://zhidao.baidu.com‘
         },
         {
             id : ‘4‘,
             title : ‘百度图片‘,
             url : ‘http://image.baidu.com‘
         },
     ]
}

那么dataFormat可以定义为

var dataFormat =
{
    name : function(data){
        return ‘<a href="‘ + data.url + ‘">‘ + data.title + ‘</a>‘;
    },
    childName : ‘subWeb‘
}

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

原文地址:https://www.cnblogs.com/zengyuanjun/p/8903213.html

时间: 2024-08-10 12:51:41

CSS实现树形结构 + js加载数据的相关文章

js和css的顺序关系及js加载执行优化探索

1. head里的顺序如下,考虑会对请求有何影响: a. 外部js在css前面 <script src="1.js"></script> <link rel="stylesheet" type="text/css" href="1.css?sleep=5s"> <linkrel="stylesheet" type="text/css" href=

iScroll.js 向上滑动异步加载数据回弹问题

iScroll是一款用于移动设备web开发的一款插件.像缩放.下拉刷新.滑动切换等移动应用上常见的一些效果都可以轻松实现. 现在最新版本是5.X,官网这里:http://iscrolljs.com/ 下面是按照官网给的Demo,写的一个异步加载数据实例: 1 <title>iScroll demo: click</title> 2 <script src="~/Scripts/iscroll5/jquery-1.10.2.js"></scrip

[JS前端开发] js/jquery控制页面动态加载数据 滑动滚动条自动加载事件

页面滚动动态加载数据,页面下拉自动加载内容 相信很多人都见过瀑布流图片布局,那些图片是动态加载出来的,效果很好,对服务器的压力相对来说也小了很多 有手机的相信都见过这样的效果:进入qq空间,向下拉动空间,到底部时,会动态加载剩余的说说或者是日志 今天我们就来看看他们的实现思路和js控制动态加载的代码 下面的代码主要是控制滚动条下拉时的加载事件的 在下面代码说明出,写上你的操作即可,无论是加载图片还是加载记录数据  都可以 别忘了引用jquery类库 [JavaScript] 纯文本查看 复制代码

D3.js加载csv和json数据

1.加载数据的基本命令 D3提供了方法可以对不同的数据类型进行加载,比如d3.text(), d3.xml(), d3.json(), d3.csv(), 和d3.html(). <!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>test</title> &l

FusionCharts简单教程(二)-----使用js加载图像和setDataXML()加载数据

前面一篇对FusionCharts进行了一个简单的介绍,而且建立了我们第一个图形,但是那个是在HTML中使用<OBJECT> 和<EMBED>标记来加载图形的,但是这样做是非常不“理智”的.这样做除了代码量比较大外,还有并不是所有的人能够看懂上面的代码.但是 使用JS后就可以避免上面几个问题了. 一.使用JS加载FusionCharts图形 下面就分五个步骤讲解如何使用js来加载FusionCharts图形. 第一步:导入FusionCharts.js文件 [javascript]

js循环加载数据列表

js循环加载数据列表 //订单渲染 function buildShowInfoDiv(data){ for(i in data.data){ var bussNo = data.data[i].bussNo; var items='<div class="weui-cells" onclick="selectOneOrder(\''+bussNo+'\')">' items+='<div class="weui-cell"&g

Eclipse中使用Tomcat加载项目在浏览器中访问的时候JS和CSS等静态文件无法加载的问题

首先,我的Eclipse是引用外部的Tomcat 引用外部Tomcat会在左侧生成一个Server文件夹,相当于复制了一份Tomcat到Eclipse的安装目录里 具体Tomcat所在目录可以在这进行查看 双击Tomcat服务,会打开一个窗口,然后点击Open launch configuration,可打开配置窗口,在这里可以查看到具体服务所在位置. 接下来步入正题,正如题目所说,Eclipse中使用Tomcat加载项目在浏览器中访问的时候JS和CSS等静态文件无法加载,如图 仔细看下路径,会

JS下拉加载数据

判断页面是否到底了,如果到底了,则加载新数据进来 自总结要点 1.拉到最底时,会请求数据,此时如果滚动未停止,那么会重复加载数据,此举浪费服务器时间 解决办法是,设置一个变量,在加载之前,将它置为真.那么在拉到最底时判断一下这个变量值再加载 在请求数据的方法里,回调 函数中成功时,再将变量值置为假.如果有分页值,那么还要将分页值加1.本页的DEMO的分页参数是放在隐藏域中的 判断依据 以下是网上抄的 首先理解三个dom元素,分别是:clientHeight.offsetHeight.scroll

MiniUI treeGrid 动态加载数据与静态加载数据的区别

说明:treegrid静态数据加载时数据结构是一棵树包含children节点集合,而采用动态加载数据时数据是List结构的具体项. 静态加载数据 test1.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="ht