Javascript 如何递归地创建UL/LI';来自JSON数据的s-多层
我正在尝试使用以下JSON数据在递归内部函数中创建以下类似结构,运气不好,确实需要一些帮助,因此如果有人可以提供帮助,请提供帮助。先谢谢你Javascript 如何递归地创建UL/LI';来自JSON数据的s-多层,javascript,json,recursion,menu,Javascript,Json,Recursion,Menu,我正在尝试使用以下JSON数据在递归内部函数中创建以下类似结构,运气不好,确实需要一些帮助,因此如果有人可以提供帮助,请提供帮助。先谢谢你 <ul> <li></li> <li> <a href=""></a> <div> <ul> <li> &l
<ul>
<li></li>
<li>
<a href=""></a>
<div>
<ul>
<li>
<a href=""></a>
<div>
....etc
</div>
</li>
</ul>
</div>
</li>
</ul>
我创建的代码(不完整,这是我需要帮助的脑筋急转弯)是:
$(函数(){
$.fn.dropdown=功能(设置){
var=这个;
变量设置=$.extend({},$.fn.dropdown.defaults,settings);
var方法={
isArray:函数(o){
返回Object.prototype.toString.call(o)='[objectarray]';
},
createDropdownCode:函数(arr){
var菜单=arr.menu;
var html=null;
var menusort=功能(菜单){
html=那个;
查找(“li”)。每个(函数(idx){
var menuList=菜单[idx].sub;
var baseContainer=$(这个);
var计数=-1;
var subsort=(函数(){
计数+=1;
返回功能(子菜单,pb){
var子块;
子块=$(“”)。追加(“
”);
if(methods.isArray(子菜单)){
对于(var i=0;iul=>li
if(settings.jsonData==undefined | | settings.jsonData==null){
console.warn('没有传递JSON数据')
返回;
}否则{
if(!methods.isArray(settings.jsonData.menu)){
console.warn('没有传递JSON数据')
return;//错误,没有数据!
}
}
//var html=methods.createBlock(settings.jsonData.menu[0].sub);
var html=methods.createDropdownCode(settings.jsonData);
//console.log(html)
}
}
方法init();
归还;
}
$.fn.dropdown.defaults={
jsonData:null
}
})
$(“#菜单”)。下拉列表({
jsonData:JSON
});
使用了集成代码,这要感谢给出了足够接近答案的个人——尽管他会研究其他人
$.fn.dropdown = function(settings){
var that = this;
var settings = $.extend({}, $.fn.dropdown.defaults, settings);
var methods = {
createDropDownCode: function(arr){
// loop through li's of primary menu
that.find("li").each(function(idx){
$(this).append( menusort(arr.menu[idx].sub) );
function menusort(data){
if(data !== null)
var html = "<div><ul>";
for(item in data){
html += "<li>";
if(typeof(data[item].sub) === 'object'){
html += "<a href='" + data[item].link + "'>" + data[item].name + "</a>";
if($.isArray(data[item].sub))
html += menusort(data[item].sub);
}
html += "</li>"
}
if(data !== null)
html += "</ul></div>";
return html;
}
})
},
init: function(){
var html = methods.createDropDownCode(settings.jsonData);
}
}
methods.init();
}
$.fn.dropdown=功能(设置){
var=这个;
变量设置=$.extend({},$.fn.dropdown.defaults,settings);
var方法={
createDropDownCode:函数(arr){
//循环浏览主菜单中的li
查找(“li”)。每个(函数(idx){
$(this.append(menusort(arr.menu[idx].sub));
函数菜单排序(数据){
如果(数据!==null)
var html=“”;
用于(数据中的项目){
html+=“- ”;
if(typeof(数据[项].sub)==“对象”){
html+=“”;
if($.isArray(数据[项目].sub))
html+=menusort(数据[项].sub);
}
html+=“
”
}
如果(数据!==null)
html+=“
”;
返回html;
}
})
},
init:function(){
var html=methods.createDropDownCode(settings.jsonData);
}
}
方法init();
}
在每个元素上调用两个函数makeUL
和makeLI
makeUL
调用makeLI
,如果存在子元素,则调用makeUL
:
function makeUL(lst) {
...
$(lst).each(function() { html.push(makeLI(this)) });
...
return html.join("\n");
}
function makeLI(elem) {
...
if (elem.sub)
html.push('<div>' + makeUL(elem.sub) + '</div>');
...
return html.join("\n");
}
函数makeUL(lst){
...
$(lst).each(function(){html.push(makeLI(this))});
...
返回html.join(“\n”);
}
函数makeLI(elem){
...
if(要素子项)
html.push(“”+makeUL(elem.sub)+“”);
...
返回html.join(“\n”);
}
需要根据您的需要进行调整,但您已经想到了。您可以尝试我刚刚编写的递归函数:
function buildList(data, isSub){
var html = (isSub)?'<div>':''; // Wrap with div if true
html += '<ul>';
for(item in data){
html += '<li>';
if(typeof(data[item].sub) === 'object'){ // An array will return 'object'
if(isSub){
html += '<a href="' + data[item].link + '">' + data[item].name + '</a>';
} else {
html += data[item].id; // Submenu found, but top level list item.
}
html += buildList(data[item].sub, true); // Submenu found. Calling recursively same method (and wrapping it in a div)
} else {
html += data[item].id // No submenu
}
html += '</li>';
}
html += '</ul>';
html += (isSub)?'</div>':'';
return html;
}
函数构建列表(数据,ISUB){
var html=(isSub)?“”;//如果为true,则用div换行
html+='';
用于(数据中的项目){
html+=“- ”;
如果(typeof(data[item].sub)==“object”){//数组将返回“object”
如有(b){
html+='';
}否则{
html+=data[item].id;//找到了子菜单,但找到了顶级列表项。
}
html+=buildList(data[item].sub,true);//找到子菜单。递归调用相同的方法(并将其包装在div中)
}否则{
html+=数据[项].id//无子菜单
}
html+='
';
}
html+='
';
html+=(ISUB)?“”:“”;
返回html;
}
它返回菜单的html,所以像这样使用:var html=buildList(JSON.menu,false);
我相信它会更快,因为它是纯JavaScript,并且不会为每次迭代创建文本节点或DOM元素。只需在完成后调用.innerHTML
或$('…').html()
,而不是立即为每个菜单添加html
jsfiddle:此解决方案使用单个递归函数。我通过使用数组的映射()
函数简化了逻辑
$(函数(){
$(“body”).html(makeUnorderedList(getData().menu));
});
函数makeUnorderedList(数据,li){
返回$(').append(data.map)(函数(el){
var li=li | |$(“- ”);
如果(el.id | | el.link)li.append($(''){
文本:el.id | | el.link,
href:“#”+(el.id | | el.link),
姓名:el.name
}));
if(el.sub)li.append(makeUnorderedList(el.sub,li));
返回李;
}));
}
函数getData(){
返回{
function makeUL(lst) {
...
$(lst).each(function() { html.push(makeLI(this)) });
...
return html.join("\n");
}
function makeLI(elem) {
...
if (elem.sub)
html.push('<div>' + makeUL(elem.sub) + '</div>');
...
return html.join("\n");
}
function buildList(data, isSub){
var html = (isSub)?'<div>':''; // Wrap with div if true
html += '<ul>';
for(item in data){
html += '<li>';
if(typeof(data[item].sub) === 'object'){ // An array will return 'object'
if(isSub){
html += '<a href="' + data[item].link + '">' + data[item].name + '</a>';
} else {
html += data[item].id; // Submenu found, but top level list item.
}
html += buildList(data[item].sub, true); // Submenu found. Calling recursively same method (and wrapping it in a div)
} else {
html += data[item].id // No submenu
}
html += '</li>';
}
html += '</ul>';
html += (isSub)?'</div>':'';
return html;
}
var jsonstring = [{
"id": '1',
"children": [{
"id": '2'
}, {
"id": '3',
"children": [{
"id": '4'
}]
}]
}, {
"id": '5'
}];
var htmlStr= recurse( jsonstring );
$('#test').append(htmlStr);
function recurse( data ) {
var htmlRetStr = "<ul>";
for (var key in data) {
if (typeof(data[key])== 'object' && data[key] != null) {
var x=key*1;
if(isNaN(x)){
htmlRetStr += "<li>" + key + ":<ul>";
}
htmlRetStr += recurse( data[key] );
htmlRetStr += '</ul></li>';
} else {
htmlRetStr += ("<li>" + key + ': "' + data[key] + '"</li >' );
}
};
htmlRetStr += '</ul >';
return( htmlRetStr );
}
<div id="test"></div>
li ul ul li {
padding-left: 10px;
}
li ul ul ul {
padding: 0px;
}
function drawRecElements(arr, html, elements) {
if (typeof (html) === 'undefined') {
var html = '';
}
if (typeof (elements) === 'undefined') {
var elements = {child: '<li>', childClose: '</li>', parent: '<ul>', parentClose: '</ul>'};
}
if (typeof (arr) === 'string') {
return elements.child + arr + elements.childClose;
} else if (typeof (arr) === 'object') {
for (i in arr) {
if (typeof (arr[i]) === 'string') {
html += elements.parent + elements.child + i + elements.childClose + elements.child + arr[i] + elements.childClose + elements.parentClose;
} else if(typeof (i) === 'string' && (isNaN(i))){
html += elements.parent + elements.child + i + elements.childClose + elements.child + drawRecElements(arr[i],'',elements) + elements.childClose + elements.parentClose;
} else if (typeof (arr[i]) === 'object') {
html = drawRecElements(arr[i], html,elements);
}
}
}
return html;
}
var config = {
"Menu-1-Level-1": {
"label": "Menu-1-Level-1",
"type": "treeView",
"class": "Menu-1-Level-1",
"children": [
{
label: "Menu-1-Level-2",
type: "treeView",
"class": "Menu-1-Level-2",
children: [
{
label: "Menu-1-Level-3",
class: "Menu-1-Level-3"
}
]
},
{
label : "Menu-2-Level-2",
class: "Menu-2-Level-2"
}
]
},
"Menu-2-Level-1": {
"label": "Menu-2-Level-1",
"type": "treeView",
"class": "Menu-2-Level-1",
"children": [
{
label: "Menu-1-Level-2",
class: "Menu-1-Level-2",
type: "treeView",
children: [
{
label: "Menu-1-Level-3",
class: "Menu-1-Level-3"
}
]
},
{
label : "Menu-2-Level-2",
class : "Menu-2-Level-2"
}
]
}
};
<!DOCTYPE html>
<html>
<head>
<title>Tree Menu</title>
<script src="http://code.jquery.com/jquery-1.11.2.min.js" type="text/javascript"></script>
<script src="tree.js" type="text/javascript"></script>
<link href="tree.css" rel="stylesheet">
</head>
<body>
<div class="treeContainer">
<div class="tree"></div>
</div>
<script src="testPage.js" type="text/javascript"></script>
</body>
</html>
var tree;
tree = function (treeNodeParent, dataObj) {
this.dataObj = dataObj;
this.treeNodeParent = treeNodeParent;
this.treeNode = $(document.createElement("ul")).addClass("treeNode");
};
tree.prototype.expandCollapse = function (e) {
var target = $(e.currentTarget), parentLabel = target.parent();
if (parentLabel.hasClass("collapsed")) {
parentLabel.removeClass("collapsed").addClass("expanded");
} else {
parentLabel.addClass("collapsed").removeClass("expanded");
}
};
tree.prototype.attachEvents = function () {
var me = this;
me.treeNodeParent.delegate(".collapsed label, .expanded label", "click", me.expandCollapse);
};
tree.prototype.attachMarkUp = function () {
var me = this;
me.treeNodeParent.append(me.treeNode);
};
tree.prototype.getEachNodeMarkup = function (nodeObj, rootNode, selector) {
var selectedNode, i, me = this;
if (nodeObj.children) {
if (!selector) {
selectedNode = rootNode;
} else {
selectedNode = rootNode.find(selector);
}
nodeObj.class = nodeObj.class ? nodeObj.class : "";
selectedNode.append($.parseHTML("<li name=" + nodeObj.label + " class='collapsed " + nodeObj.class + "'>" + "<label>" + nodeObj.label + "</label>" + "<ul></ul></li>"));
selector = selector + " li[name=" + nodeObj.label + "] > ul";
for (i = 0; i < nodeObj.children.length; i = i + 1) {
me.getEachNodeMarkup(nodeObj.children[i], rootNode, selector);
}
} else {
nodeObj.class = nodeObj.class ? nodeObj.class : "";
rootNode.find(selector).append($.parseHTML("<li name=" + nodeObj.label + " class='" + nodeObj.class + "'>" + "<label>" + nodeObj.label + "</label>" + "</li>"));
}
};
tree.prototype.getTree = function () {
var component, me = this;
for (component in me.dataObj) {
if (me.dataObj.hasOwnProperty(component)) {
me.getEachNodeMarkup(me.dataObj[component], me.treeNode, "");
}
}
me.attachMarkUp();
me.attachEvents();
return me.treeNode;
};
.treeNode .collapsed > ul, .collapsed > li {
display: none;
}
.treeNode .expanded > ul, .expanded > li {
display: block;
}
// the variable "config" is nothing but the config JSON defined initially.
treeNode = new tree($('.treeContainer .tree'), config);
treeNodeObj = treeNode.getTree();
var foo=(arg)=>
`<ul>
${arg.map(elem=>
elem.sub?
`<li>${foo(elem.sub)}</li>`
:`<li>${elem.name}</li>`
).join('')}
</ul>`
var bar = [
{
name: 'Home'
}, {
name: 'About'
}, {
name: 'Portfolio'
}, {
name: 'Blog'
}, {
name: 'Contacts'
}, {
name: 'Features',
sub: [
{
name: 'Multipage'
}, {
name: 'Options',
sub: [
{
name: 'General'
}, {
name: 'Sidebars'
}, {
name: 'Fonts'
}, {
name: 'Socials'
}
]
}, {
name: 'Page'
}, {
name: 'FAQ'
}
]
}
]
var result=foo(bar)