为了账号安全,请及时绑定邮箱和手机立即绑定

用于构建树的Javascript递归函数

用于构建树的Javascript递归函数

神不在的星期二 2021-12-12 15:36:33
我正在使用JavaScript和jQuery作为客户端脚本。我对Recursive functions. 我有一个 JSON 数据,如下所示,我尝试通过编写递归函数使用下面的 JSON 数据制作树结构,但我无法构建树结构。所需输出:var treeNode = {                    id: 101, // random                    text: object.name,                    icon: "fas fa-plus",                    subNode: {                        // id, text, icon and subNode of Children object                        // recursive data,  So on....                     }                };任何人都可以建议我或帮助我Recursive function根据上述 JSON 数据编写 javascript 或 jQuery ,以便我可以构建树结构。我知道我在寻求帮助,因为我对递归函数的了解较少。
查看完整描述

2 回答

?
大话西游666

TA贡献1817条经验 获得超14个赞

它可以是这样的,使用 json 数据模型


<!doctype html>


<html>

  <head>

    <link rel="stylesheet" href="lib/style.css">

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

  </head>


  <body>

    <div id="myDiv"></div>

  </body>

  <script>


var treeData={

   "Id":"10",

   "text":"Document Categories",

   "icon":"fas fa-plus",

   "subNode":

    [

      {

         "Id":"11",

         "text":"Pdf Documents",

         "icon":"fas fa-plus",

         "subNode":[

            {

               "Id":"31",

               "text":"Book Pdfs",

               "icon":"fas fa-plus",

                "subNode":[]

            },

            {

               "Id":"32",

               "text":"EPub",

               "icon":"fas fa-plus",

               "subNode":[

                  {

                     "Id":"20",

                     "text":"EBook Epubs1",

                     "icon":"fas fa-plus",

                     "subNode":[]

                  },

                  {

                     "Id":"30",

                     "text":"EBook Epubs2",

                     "icon":"fas fa-plus",

                     "subNode":[]

                  }

               ]

            }

         ]

      },

      {

         "Id":"33",

         "text":"Text Documents",

         "icon":"fas fa-plus",

         "subNode":[

            {

               "Id":"32",

               "text":"Book Text",

               "icon":"fas fa-plus",

                "subNode":[]

            },

            {

               "Id":"35",

               "text":"Automatic Text",

               "icon":"fas fa-plus",

               "subNode":[]

            }

         ]

      }

   ]

};


    var newTree = AddRecursive(null, treeData);

    var treeDiv = $('#myDiv');

    treeDiv.append(newTree);



function AddRecursive(tree, data) {

  if (tree == null) {

    tree = $('<ul/>');

    tree.attr('id', 'treeID');

  }


  var listU = $('<ul />');

  listU.addClass('ul class');


  var listItem = $('<li />');

  listItem.addClass('li class');

  listItem.attr('data-id', data.Id);


  var link = $('<a />');

  var i = $('<i/>').addClass('fa fa-folder');

  link.append(i);


  //link.addClass("linkClass");

  link.append(data.text);

  listItem.append(link);


  if (data.subNode.length > 0) {

    var span = $(' <span />');

    span.addClass('fa-chevron-down');

    link.append(span);

  }


  listU.append(listItem);

  tree.append(listU);


  for (i in data.subNode) {

    AddRecursive(listItem, data.subNode[i]);

  }

  return tree;

}




  </script>

</html>


查看完整回答
反对 回复 2021-12-12
?
阿波罗的战车

TA贡献1862条经验 获得超6个赞

如果我们稍微抽象一下,就可以很容易地编写一个通用的树映射函数。然后我们可以提供两个回调函数:一个查找输入的子节点,一个根据输入和映射的子节点构建输出节点。事实证明,这样的函数出奇的简单:


const mapTree = (getChildren, transformNode) => (tree) =>

  transformNode (

    tree, 

    (getChildren (tree) || []) .map (mapTree (getChildren, transformNode))

  )

对于您的数据,getChildren简直就是(node) => node._children


节点转换可能很简单:


const transformNode = (node, children) => 

  ({

    id: node.$id,         // or a randomizing call?

    text: node.name,

    icon: "fas fa-plus",  // is this really a fixed value?

    subNode: children

  })

把这些放在一起,我们得到


const mapTree = (getChildren, transformNode) => (tree) =>

  transformNode (

    tree, 

    (getChildren (tree) || []) .map (mapTree (getChildren, transformNode))

  )


const kids = (node) => node._children


const transformNode = (node, children) => 

  ({

    id: node.$id,

    text: node.name,

    icon: "fas fa-plus",    

    subNode: children

  })


const myTransform = mapTree (kids, transformNode)


const jsonData = { "$id": "45", "_children": [{ "$id": "46", "_children": [{ "$id": "47", "_children": [{ "$id": "48", "_children": [{ "$id": "49", "_children": null, "id": "Test1", "text": "Text1", "name": "name1", "parent": null, "root": { "$ref": "49" }, "depth": 0, "children": [] }], "id": "id1", "text": "text2", "name": "name2", "parent": null, "root": { "$ref": "48" }, "depth": 0, "children": [{ "$ref": "49" }] }], "id": "id3", "text": "text4", "name": "name4", "parent": null, "root": { "$ref": "47" }, "depth": 0, "children": [{ "$ref": "48" }] }, { "$id": "50", "_children": [{ "$id": "51", "_children": [{ "$id": "52", "_children": null, "id": "id6", "text": "text6", "name": "name6", "parent": null, "root": { "$ref": "52" }, "depth": 0, "children": [] }], "id": "id7", "text": "text7", "name": "name7", "parent": null, "root": { "$ref": "51" }, "depth": 0, "children": [{ "$ref": "52" }] }], "id": "id8", "text": "text8", "name": "name8", "parent": null, "root": { "$ref": "50" }, "depth": 0, "children": [{ "$ref": "51" }] }], "id": "id9", "text": "text9", "name": "name9", "parent": null, "root": { "$ref": "46" }, "depth": 0, "children": [{ "$ref": "47" }, { "$ref": "50" }] }, { "$id": "53", "_children": [{ "$id": "54", "_children": null, "id": "id10", "text": "text10", "name": "name10", "parent": null, "root": { "$ref": "54" }, "depth": 0, "children": [] }], "id": "id11", "text": "text11", "name": "name11", "parent": null, "root": { "$ref": "53" }, "depth": 0, "children": [{ "$ref": "54" }] }], "id": "0", "text": "0", "name": "", "parent": null, "root": { "$ref": "45" }, "depth": 0, "children": [{ "$ref": "46" }, { "$ref": "53" }] }


console .log (myTransform (jsonData))


这与您请求的输出略有不同。你写了subNode: { ... },但我返回了一个对象数组,subNodes: [ ... ],因为我在这里没有任何真正意义上的普通对象。


此外,subNodes如果输入节点没有子节点,这将产生一个空数组。如果您不想拥有该subNodes财产,则可以更换


    subNode: children


    ...(children .length ? {subNode: children} : {})

显然,您不需要命名的助手,并且可以mapTree使用如下匿名函数进行调用:


const myTransform = mapTree (

  (node) => node._children, 

  (node, children) => 

    ({

      id: node.$id,

      text: node.name,

      icon: "fas fa-plus",    

      subNode: children

    })

)

这个mapTree函数很容易编写,因为我在编写它时不必考虑输出或输入格式的任何细节。但也许这种抽象对我没有帮助,除了这里我永远不会使用它。如果是这样,我可以通过直接插入硬编码回调来简单地重新设计抽象版本。只需稍加操作,即可将其变成这个版本:


const newTransform = (node) =>

  ({

    id: node.$id,

    text: node.name,

    icon: "fas fa-plus",    

    subNode: (node._children || []).map(newTransform)

  })


const jsonData = { "$id": "45", "_children": [{ "$id": "46", "_children": [{ "$id": "47", "_children": [{ "$id": "48", "_children": [{ "$id": "49", "_children": null, "id": "Test1", "text": "Text1", "name": "name1", "parent": null, "root": { "$ref": "49" }, "depth": 0, "children": [] }], "id": "id1", "text": "text2", "name": "name2", "parent": null, "root": { "$ref": "48" }, "depth": 0, "children": [{ "$ref": "49" }] }], "id": "id3", "text": "text4", "name": "name4", "parent": null, "root": { "$ref": "47" }, "depth": 0, "children": [{ "$ref": "48" }] }, { "$id": "50", "_children": [{ "$id": "51", "_children": [{ "$id": "52", "_children": null, "id": "id6", "text": "text6", "name": "name6", "parent": null, "root": { "$ref": "52" }, "depth": 0, "children": [] }], "id": "id7", "text": "text7", "name": "name7", "parent": null, "root": { "$ref": "51" }, "depth": 0, "children": [{ "$ref": "52" }] }], "id": "id8", "text": "text8", "name": "name8", "parent": null, "root": { "$ref": "50" }, "depth": 0, "children": [{ "$ref": "51" }] }], "id": "id9", "text": "text9", "name": "name9", "parent": null, "root": { "$ref": "46" }, "depth": 0, "children": [{ "$ref": "47" }, { "$ref": "50" }] }, { "$id": "53", "_children": [{ "$id": "54", "_children": null, "id": "id10", "text": "text10", "name": "name10", "parent": null, "root": { "$ref": "54" }, "depth": 0, "children": [] }], "id": "id11", "text": "text11", "name": "name11", "parent": null, "root": { "$ref": "53" }, "depth": 0, "children": [{ "$ref": "54" }] }], "id": "0", "text": "0", "name": "", "parent": null, "root": { "$ref": "45" }, "depth": 0, "children": [{ "$ref": "46" }, { "$ref": "53" }] }


console .log (newTransform (jsonData))


这里有一个重要的点。这个通用函数比我尝试编写一些东西来直接转换格式要容易得多。虽然过早的抽象存在危险,但它也可以提供显着的好处。我可能会选择只保留最后一个版本,但通用抽象简化了它的开发。


查看完整回答
反对 回复 2021-12-12
  • 2 回答
  • 0 关注
  • 170 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信