How can I recursively create a UL/LI's from JSON data - multiple layers deep
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am trying to use use the following JSON data to create the following similar structure in a recursive inner function with not much luck, really need some help and so if anyone can assist please do. Thank you in advance.
....etc
the JSON data I am using is as follows:
var JSON = { menu: [ {id: '0',sub: [ {name: 'lorem ipsum 0-0',link: '0-0', sub: null}, {name: 'lorem ipsum 0-1',link: '0-1', sub: null}, {name: 'lorem ipsum 0-2',link: '0-2', sub: null} ] }, {id: '1',sub: null}, {id: '2',sub: [ {name: 'lorem ipsum 2-0',link: '2-0', sub: null}, {name: 'lorem ipsum 2-1',link: '2-1', sub: null}, {name: 'lorem ipsum 2-2',link: '2-2', sub: [ {name: 'lorem ipsum 2-2-0',link: '2-2-0', sub: null}, {name: 'lorem ipsum 2-2-1',link: '2-2-1', sub: null}, {name: 'lorem ipsum 2-2-2',link: '2-2-2', sub: null}, {name: 'lorem ipsum 2-2-3',link: '2-2-3', sub: null}, {name: 'lorem ipsum 2-2-4',link: '2-2-4', sub: null}, {name: 'lorem ipsum 2-2-5',link: '2-2-5', sub: null}, {name: 'lorem ipsum 2-2-6',link: '2-2-6', sub: null} ]}, {name: 'lorem ipsum 2-3',link: '2-3', sub: null}, {name: 'lorem ipsum 2-4',link: '2-4', sub: null}, {name: 'lorem ipsum 2-5',link: '2-5', sub: null} ] }, {id: '3',sub: null} ] }
and the code I have created (incomplete, this is the brain teaser I need help on) is:
$(function(){ $.fn.dropdown = function(settings){ var that = this; var settings = $.extend({}, $.fn.dropdown.defaults, settings); var methods = { isArray: function(o){ return Object.prototype.toString.call(o) === '[object Array]'; }, createDropdownCode: function(arr){ var menu = arr.menu; var html = null; var menusort = function(menu){ html = that; that.find("li").each(function(idx){ var menuList = menu[idx].sub; var baseContainer = $(this); var count = -1; var subsort = (function(){ count += 1; return function(submenu, pb){ var subblock; subblock = $("").append('
integrated code used, thanks to the individual that gave a close enough answer - Although will study the others.
$.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 = "
"; for(item in data){ html += "
"; if(typeof(data[item].sub) === 'object'){ html += "" + data[item].name + ""; if($.isArray(data[item].sub)) html += menusort(data[item].sub); } html += "
" } if(data !== null) html += "
"; return html; } }) }, init: function(){ var html = methods.createDropDownCode(settings.jsonData); } } methods.init(); }
回答1:
You can try this recursive function I've just coded:
function buildList(data, isSub){ var html = (isSub)?'
':''; // Wrap with div if true html += '
'; for(item in data){ html += '
'; if(typeof(data[item].sub) === 'object'){ // An array will return 'object' if(isSub){ html += '' + data[item].name + ''; } 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 += '
'; } html += '
'; html += (isSub)?'
':''; return html; }
It returns the html for the menu, so use it like that: var html = buildList(JSON.menu, false);
I believe it is faster because it's in pure JavaScript, and it doesn't create text nodes or DOM elements for every iteration. Just call .innerHTML or $('...').html() at the end when you're done instead of adding HTML immediately for every menu.
Here is a more dynamic approach. You get to choose how your list items are rendered and what the child property is. The mapFunc paramater is a callback that gives you access to the current child node and its parent.
The scope of the mapFunc is the item. So you could use item as well as this to refer to said item.
li ul ul li { padding-left: 10px; } li ul ul ul { padding: 0px; }
回答5:
This is like a complete solution for generating UL/LI recursively from JSON config, which has customizable classes for each node and support of expand and collapse events for each node. This provides just a basic working model, from which you ll be able to expand and customize to your needs.
// the variable "config" is nothing but the config JSON defined initially. treeNode = new tree($('.treeContainer .tree'), config); treeNodeObj = treeNode.getTree();
I was searching for general parent child element function and I saw these answers, and I took some pieces of code from here and there and made this function. I decided to share my code as an answer, in case someone like me will find this post when he is searching for a general parent child html element draw function:
function drawRecElements(arr, html, elements) { if (typeof (html) === 'undefined') { var html = ''; } if (typeof (elements) === 'undefined') { var elements = {child: '
', childClose: '
', parent: '
', parentClose: '
'}; } 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; }