zoukankan      html  css  js  c++  java
  • 支持两种数据结构的极简单的文件树

    在开发中经常遇到文件树这种需求,一般在网上搜到的,都是一些写的比较死的,不容易修改,很难达到自己的个性化需求,其实文件树也不难,只是用到的递归算法,从根节点一直递归到叶子节点,下面通过这个例子,给大家讲一下,文件树的实现。


    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    ul, li {
    list-style: none;
    / / 取消掉ul, li的默认样式
    }

    ul {
    padding-left: 20px;
    }

    .close { /**关闭按钮**/
    display: inline-block;
    15px;
    height: 15px;
    background: url("close.png") no-repeat center;
    background-size: contain;
    }

    .open { /**打开按钮**/
    display: inline-block;
    15px;
    height: 15px;
    background: url("open.png") no-repeat center;
    background-size: contain;
    }

    .leaf { /**叶子节点**/
    display: inline-block;
    15px;
    height: 15px;
    background: url("leaf.png") no-repeat center;
    background-size: contain;
    }

    .leafName {
    color: green;
    padding-left: 10px;
    padding-right: 10px;

    }

    .openTrue {
    color: gray;
    }
    </style>
    </head>
    <body>
    <div id="tree"></div>
    <script type="text/javascript" src="../../../static/plugins/jquery/jquery-1.9.1.js"></script>
    <script>
    //第一种数据结构包含子元素
    var arr = [
    {
    name: "父节点1 - 展开", open: true,
    children: [
    {
    name: "父节点11 - 折叠",
    children: [
    {name: "叶子节点111", nid: "nid"},
    {name: "叶子节点112",},
    {name: "叶子节点113"},
    {name: "叶子节点114"}
    ]
    },
    {
    name: "父节点12 - 折叠",
    children: [
    {name: "叶子节点121"},
    {name: "叶子节点122"},
    {name: "叶子节点123"},
    {name: "叶子节点124"}
    ]
    },
    {name: "父节点13 - 没有子节点", isParent: true}
    ]
    },
    {
    name: "父节点2 - 折叠",
    children: [
    {
    name: "父节点21 - 展开",
    children: [
    {name: "叶子节点211"},
    {name: "叶子节点212"},
    {name: "叶子节点213"},
    {name: "叶子节点214"}
    ]
    },
    {
    name: "父节点22 - 折叠",
    children: [
    {name: "叶子节点221"},
    {name: "叶子节点222"},
    {name: "叶子节点223"},
    {name: "叶子节点224"}
    ]
    },

    ]
    },


    ];


    //第二种数据结构有父级id的
    var arr1 = [
    {id: 1, pId: 0, name: "父节点1 - 展开", open: true},
    {id: 11, pId: 1, name: "父节点11 - 折叠"},
    {id: 111, pId: 11, name: "叶子节点111"},
    {id: 112, pId: 11, name: "叶子节点112"},
    {id: 113, pId: 11, name: "叶子节点113"},
    {id: 114, pId: 11, name: "叶子节点114"},
    {id: 12, pId: 1, name: "父节点12 - 折叠"},
    {id: 121, pId: 12, name: "叶子节点121"},
    {id: 122, pId: 12, name: "叶子节点122"},
    {id: 123, pId: 12, name: "叶子节点123"},
    {id: 124, pId: 12, name: "叶子节点124"},
    {id: 13, pId: 1, name: "父节点13 - 没有子节点", isParent: true},
    {id: 2, pId: 0, name: "父节点2 - 折叠"},

    ];

    paintingTree(arr, "tree")
    //渲染树
    //arr为数据,id为树的容器的id
    function paintingTree(arr, id) {
    if (arr[0]) {
    //判断是哪一种数据结构
    if (arr[0]["pId"] !== undefined) {//如果是还有父元素id的第二种数据结构,那么先转换成第一种数据结构
    arr = removeEmptyFromPaintData(arr)
    }

    }

    var str = ""
    //渲染树
    function createTree(arr) {
    if (arr) {//判断arr是否有效
    var children = arr;
    str += "<ul>";
    for (var j = 0; j < children.length; j++) {
    str += "<li>"
    if (children[j]["children"]) {//判断是否有子节点
    if (children[j]["open"]) {//判断是否是展开的
    str += "<div open='true'><span class='close'></span><span class='openTrue'>" + children[j]["name"] + "</span></div>";
    } else {
    str += "<div open='false'><span class='open'></span><span class='openTrue'>" + children[j]["name"] + "</span></div>";
    }

    } else {
    if (children[j]["isParent"]) {//判断是否是父节点
    str += "<div open='true'><span class='open'></span>" + children[j]["name"] + "</div>";
    } else {
    str += "<div><span class='leaf'></span><span class='leafName'></span>" + children[j]["name"] + "</div>";
    }

    }

    createTree(children[j]["children"])//递归调用方法,一层一层渲染
    str += "</li>"
    }
    str += "</ul>";
    }
    }

    //渲染树
    createTree(arr)

    $("#" + id).hide()//渲染完成后先进行隐藏
    $("#" + id).html(str)
    $("[open=true]").each(function () {//含有[open=true]属性的下一个元素(ul)进行展示
    $(this).next().show()
    })
    $("[open=false]").each(function () {//含有[open=false]属性的下一个元素(ul)进行隐藏
    $(this).next().hide();
    })
    $(document).on("click", ".close", function () {//给含有[open=true]属性的元素绑定点击事件

    $(this).parent().next().hide();//当前元素的父元素(div)的下一个元素(ul)隐藏
    $(this).addClass("open").removeClass("close");//当前元素样式改为关闭样式

    })
    $(document).on("click", ".open", function () {
    $(this).parent().next().show();
    $(this).addClass("close").removeClass("open");
    })
    $("#" + id).show();
    /**把简单的数据转化成渲染数据
    第一个参数和第二个参数是同一个数组**/
    function createPaintDataFromSimpleData(zNodes, Nodes) {
    for (var i = 0; i < zNodes.length; i++) {//循环第一个参数
    if (!!zNodes[i]) {//如果这个元素是有效的 不为"" 0 false null undefind
    zNodes[i]["children"] = [];//给元素增加children属性,并复制为空数组
    for (var j = 0; j < Nodes.length; j++) {//循环第二个参数
    if (!!Nodes[j]) {//如果这个元素是有效的 不为"" 0 false null undefind
    if (Nodes[j]["pId"] == zNodes[i]["id"]) {//如果第二个参数元素中的pid有等于第一个参数中当前元素的id的,那么把第二个参数中符合条件的元素都放到第一个参数当前元素children中
    if (Nodes[j]) {//保证这个值是有效的
    zNodes[i]["children"].push(Nodes[j]);
    Nodes[j] = "";//为什么不直接删掉,因为要保证循环的正常进行,就要保证数组的长度
    }
    }
    }
    }
    if (zNodes[i]["children"].length == 0) {//如果循环下来,children的长度为0,那么到此第一个参数的当前元素,到此结束
    zNodes[i]["children"] = false
    } else {//如果循环下来,children的长度不为0,第一个参数的当前元素,递归循环
    createPaintDataFromSimpleData(zNodes[i]["children"], zNodes);
    }
    }
    }
    return zNodes;//最后得到的元素是含有空字符串的元素 所以下一步,要去除空字符串
    }

    //对渲染数据清除空元素
    function removeEmptyFromPaintData(nodes) {
    var data = createPaintDataFromSimpleData(nodes, nodes);
    var arr = [];
    for (var i = 0; i < data.length; i++) {
    if (!!data[i]) {
    arr.push(data[i]);//只存放不为空字符串的元素
    }
    }
    return arr;
    }
    }


    </script>
    </body>
    </html>
  • 相关阅读:
    内嵌WORD/OFFICE的WINFORM程序——DSOFRAMER使用小结
    安装jenkins
    excel单元测试
    参数化单元测试
    单元测试参数化
    python之继承
    冒泡算法
    打印三角形
    jmeter下载地址
    python-ddt处理测试类数据
  • 原文地址:https://www.cnblogs.com/liuhao-web/p/10030778.html
Copyright © 2011-2022 走看看