3

我正在尝试动态构建菜单,并将数据输出到以下形式的 JSON 对象。

"Link 1": {
    "href":"#",
    "Sub Link 1": {
        "href":"#"
    },
    "Sub Link 2": {
        "href":"#",
        "Sub Sub Link 1": {
            "href":"#"
        },
        "Sub Sub Link 2": {
            "href":"#"
        }       
    }       
}

首先,我想知道这对于链接层次结构是否是一个好的设计。

另一方面,当我遍历数组时,我只能获得名称“Link 1”,但不能获得链接层次结构下的任何属性。

我正在使用的循环如下:

for(var item in jsonMenu) {
    console.log(item)
}

它输出:Link 1, Link 2, Link 3 但我希望能够访问该对象内的其他 JSON 对象。

我尝试嵌套另一个循环,但我得到的只是数字:0, 1, 2, 3我怀疑这是字符串的长度。

我也尝试过使用:

item.hasOwnProperty(key)

但它不起作用:它返回Uncaught Reference Error: key does not exist

任何帮助将不胜感激

编辑:

到目前为止,这是我所拥有的,但在我看来,菜单的开销太大了,到目前为止,它的执行时间为 O(n^2),我仍然需要深入一层,所以执行时间会为 O(n^3):

 for(var item in jsonMenu) {
     if(jsonMenu.hasOwnProperty(item)) {
        for(var attr in jsonMenu[item]) {   
            console.log(attr);
        }
        console.log(item + " => " + jsonMenu[item])
    }
 }
4

5 回答 5

4

如果可能的话,我建议重组源数据,以便名称是对象的属性而不是键名本身,如下所示:

{
    "name": "Link 1"
    "href":"#",
    "children": [
    {
        "name": "Sub Link 1"
        "href":"#"
    }       
}

这是更好的语义,允许您轻松添加其他属性,并且更容易处理并且可能也更容易生成,因为它更好地匹配大多数编程语言中的对象。否则,您将假设对象中的每个键都是一个新节点。

于 2013-05-02T17:51:54.747 回答
2

基于 Paul 的回答,这里有一个将此 JSON 呈现为菜单(演示)的函数:

<ul id='menu'></ul>
<script>
  var links = {
    "name": "Link 1",
    "href": "#link1",
    "children": [{
        "name": "Sub Link 1",
        "href": "#subLink1"
    }]
  },
  render = function (parent, link) {
    var element = $("<li><a href='" + link.href + "'>" + link.name + "</a></li>"),
        sublist,
        child;
    if (link.hasOwnProperty('children') && link.children.length > 0) {
        sublist = $("<ul></ul>");
        for (child = 0; child < link.children.length; child++) {
            render(sublist, link.children[child]);
        }
        element.append(sublist);
    }
    parent.append(element);
  };
  render($('#menu'), links);
</script>
于 2013-05-02T18:03:29.807 回答
1

我会重新组织你的结构,以便更容易循环和构建菜单:

{
    "Links": [{
        "href": "#",
        "Links": [{
            "href": "#",
            "Links": [{ "href": "#" }, { "href": "#" }]
         }]
    }];
}

这将允许您使用所有命名约定都相同的递归循环方法。

于 2013-05-02T17:51:36.340 回答
1

这似乎是一个完美的树状结构,其中text是一个属性,属性的值是链接的内部文本。这是一个更加灵活的结构,因为您不必手动迭代对象的属性来找出内部文本的值。

{ 
   text: "Link #1"
   href: "..."
   children: [{
      text: "Link #2",
      href: "...",
      children: []
   }, {
      text: "Link #3",
      href: "...",
      children: [{
          text: "Link #4",
          href: "...",
          children: []
      }]
   }]
}

当然,这是假设您永远只有一个链接。所以如果你想要更多,你基本上可以有一个像这样的“树”数组:

[{ 
   text: "Link #1"
   href: "..."
   children: [{
      text: "Link #2",
      href: "...",
      children: []
   }, {
      text: "Link #3",
      href: "...",
      children: [{
          text: "Link #4",
          href: "...",
          children: []
      }]
   }]
}, {
   text: "Link #5",
   href: "...",
   children []
}, {
   text: "Link #6",
   href: "...",
   children: [{
      text: "Link #7",
      href: "...",
      children: []
   }]
}]
于 2013-05-02T17:52:54.290 回答
1

我不认为架构是一个好主意,原因有两个:

  • JSON 对象无序的——我猜你想编码子菜单的顺序。
  • 你不能有一个带有标题的子菜单href(也许你以后想添加其他属性)

更好地使用对象数组,其中一个children属性是另一个数组。迭代也容易得多。就像是

{
    "name": "Link 1",
    "href":"#",
    "children": [{
        "name": "Sub Link 1",
        "href":"#"
    }, {
        "name": "Sub Link 2",
        "href":"#",
        "children": [{
            "name": "Sub Sub Link 1",
            "href":"#"
        }, {
            "name": "Sub Sub Link 2",
            "href":"#"
        }]
    }]
}
于 2013-05-02T17:53:15.057 回答