Jquery 使用JSON构建嵌套列表

Jquery 使用JSON构建嵌套列表,jquery,json,Jquery,Json,我有以下创建菜单的JSON: { "menu": { "id": "organisation-201", "class": "list", "content": { "menuitem": [{ "text": "New Journal Entry", "title": "New Journal Entry", "href

我有以下创建菜单的JSON:

{
    "menu": {
        "id": "organisation-201",
        "class": "list",
        "content": {
            "menuitem": [{
                "text": "New Journal Entry",
                "title": "New Journal Entry",
                "href": "/Organisations/201/NewJournalEntry",
                "liClass": "",
                "icon": "icon test"
            }, {
                "text": "View People",
                "title": "View People",
                "href": "/Organisations/201/People",
                "liClass": "",
                "icon": "icon test"
            }, {
                "text": "Edit",
                "title": "Edit",
                "href": "/Organisations/201/Edit",
                "liClass": "sep",
                "icon": "icon test"
            }]
        }
    }
}
然后使用jQuery构建它,就像:注意:我使用$.ajax调用json,但这里没有显示它

// Build the menu
var ul = $("<ul/>").attr("id", data.menu.id).addClass(data.menu.class);

// For each menu item
$.each(data.menu.content.menuitem, function () {
    var li = $("<li/>").appendTo(ul).addClass(this.liClass);
    var anchor = $("<a/>").appendTo(li).attr("href", this.href).attr("title", this.title);

    var span = $("<span/>").appendTo(anchor).addClass(this.icon).html(this.text)
});
好的,我要做的是构建一个嵌套的菜单结构,例如,我可以做如下标记:

<ul>
    <li>
        <a href="#">Link 1</a>
    </li>
    <li>
        <a href="#">Link 2</a>
        <ul>
            <li>
                <a href="#">Link 2.1</a>
            </li>
            <li>
                <a href="#">Link 2.2</a>
            </li>
        </ul>
    </li>
</ul>

最好的方法是什么?记住它们可能并不总是一个子菜单。。。我曾考虑过在菜单项中添加额外的参数,但嵌套菜单可能有2-3层深,因此需要灵活。如有任何想法、建议和代码示例,将不胜感激。谢谢。

您应该为每个menuitem对象添加一个名为ex content的属性,该属性可能包含其他子菜单项

{"menu": {
    "content" : {
        "menuitem": [{
            "text": "New Journal Entry",
            ...
            "content" : {
                "menuitem":[{
                    "text": "Submenu"
                    ..
                            }]
                        }
                    ]}
                }
        }
}}
每个函数都可以解析json

。它在演示中解析多个级别,最多3级,但实际上它可以做得更多

{"menu": {
    //attributes for the <ul>
    "attributes": {               
        "id": "organisation-201",
        "class": "list"
    },
    //<li>'s
    "items": [{     
        //<li> attributes               
        "attributes": {},
        //<a> attributes
        "link": {
            "text": "New Journal Entry",
            "title": "New Journal Entry",
            "href": "/Organisations/201/NewJournalEntry"
        },
        //<li> icon
        "icon": "icon test",
        //submenu of the same structure
        "menu": ...
    }]
}​}
这个结构可以通过这个紧凑的脚本来解析:

var menu = (function menuBuilder(menu) {
    var $menu = $('<ul/>').attr(menu.attributes);
    $.each(menu.items, function(itemIndex, itemData) {
        var $item = $('<li/>').attr(itemData.attributes).appendTo($menu);
        var $link = $('<a/>').appendTo($item);            
        $.each(itemData.link, function(linkKey, linkVal) {
            if (linkKey === 'text') {$link.text(linkVal);} 
            else {$link.attr(linkKey, linkVal);}
        });
        if (itemData.hasOwnProperty('menu')) {
            $item.append(menuBuilder(itemData.menu));
        }
    });
    return $menu;
}(json.menu));

$('body').append(menu);

当我需要从javscript中的数据创建动态html时,我喜欢创建隐藏的模板div,使用函数用项目的数据填充模板,然后使用jquery,类似$real_list.append$item_template.html;来构建实际的html。 所以你的菜单我想试试这样的

<div id="menu_level_template" style="display_none">
  <ul class="menu_level">

  </ul>
</div>

<div id="menu_item_template" style="display_none">
  <li>
    <a href=""></a>
  </li>
</div>

当您使用$element.html时,它接受的是内容,而不是标记本身,因此永远不会复制模板的div。递归处理任何级别的菜单。

您能修改JSON以显示3级菜单吗?这也是我问题的一部分,因为我想知道构建类似菜单的最佳方式是什么。
function parse_menu(menu_level_object, $destination)
{
  var $level_template=$('#menu_level_template');  
  $level_template.find('ul').html('');  //reset the template

  fill_menu_template_with_menu_level_data();

  $destination.append( $level_template.html() );

  var $current_level_ul = get_ul_of_just_appended_html();
  var menu_items = get_menu_items( menu_level_object );
  $.each(menu_items,function(index,menu_item)
  {
     parse_item( menu_item, $current_level_ul );
  });
}

function parse_item( menu_item, $destination )
{
  var $item_template=$('#menu_item_template');
  $item_template.html(' '); //clear the template

  fill_item_template_with_data();

  $destination.append( $item_template.html() );

  if( has_submenu( menu_item ) )
  {
    var submenu= get_submenu( menu_item );
    parse_menu( submenu, $destination );
  }
}

parse_menu(menu_data, $root_menu_location);