使用对象数组创建嵌套列表

我有一组SQL数据会经常更改,我需要定期创建一个嵌套的,无序的列表。 我已经将SQL数据转换为对象数组,但我仍然坚持从中创建无序列表的逻辑。

我试过制作一个递归函数,但我对这些没有经验,所以

数据包含以下字段:

ID Category Name ParentID 

因此,每个类别都有一个ID和一个ParentID(与另一个类别的ID匹配)。 根类别都具有相同的虚拟ParentID。

javascript对象具有相同的属性。 这是一个例子:

 var Categories = [ new Category(1, 'Root', 0), new Category(2, 'Cat1', 1), new Category(3, 'Cat2', 2), new Category(4, 'Cat3', 5), new Category(5, 'Cat4', 1), new Category(6, 'Cat5', 5), new Category(7, 'Cat6', 5), new Category(8, 'Cat7', 1), new Category(9, 'Cat8', 2), new Category(10, 'Cat9', 1), new Category(11, 'Cat10', 10), new Category(12, 'Cat11', 1), new Category(13, 'Cat12', 8) ] 

我需要使用该对象数组来创建一个如下所示的无序列表:

 
  • Cat1
    • Cat2
    • Cat8
  • Cat4
    • Cat3
    • Cat5
    • Cat6
  • Cat7
    • Cat12
  • Cat8
  • Cat9
    • Cat10
  • Cat11

目前,我最深的数据是3层,但我希望能够让脚本执行任意数量的层。

jQuery对此很好。

这是一种基于类的方法。 深度是无限的。 唯一的要求是在添加子项之前父项必须存在。

 // create class // parent is optional Category var Category = function (id, name, parent) { this.id = id; this.name = name; this.parent = null; this.children = []; if (parent) { parent.add(this); } }; Category.prototype.root = function() { if (this.parent) return this.parent.root(); return this; } // find by id Category.prototype.find = function (id) { if (this.id == id) return this; var found; for (var i = 0, il = this.children.length; i < il; i++) { if (found = this.children[i].find(id)) return found; } return null; }; // create relationship Category.prototype.add = function (cat) { cat.parent = this; this.children.push(cat); }; // render list for item Category.prototype.renderList = function ($parentElem) { var $nameElem = $('
  • ' + this.name + '
  • ').appendTo($parentElem); if (this.children.length) { this.renderChildren($('
      ').appendTo($nameElem)) } } // create child elements and add them to the parent Category.prototype.renderChildren = function ($parentElem) { for (var i = 0, il = this.children.length; i < il; i++) { this.children[i].renderList($parentElem); } } function createCategory(id, name, parentId) { rootCat.find(parentId).add(new Category(id, name)); } // add items var rootCat = new Category(1, 'root'); createCategory(2, 'Cat1', 1); createCategory(3, 'Cat2', 2); createCategory(4, 'Cat3', 3); createCategory(14, 'Cat3.5', 4); createCategory(5, 'Cat4', 1); createCategory(6, 'Cat5', 5); createCategory(7, 'Cat6', 5); createCategory(8, 'Cat7', 1); createCategory(9, 'Cat8', 2); createCategory(10, 'Cat9', 1); createCategory(11, 'Cat10', 10); createCategory(12, 'Cat11', 1); createCategory(13, 'Cat12', 8); // render rootCat.renderChildren($('#cats'));

      的jsfiddle

      演示 : http : //jsfiddle.net/4JpsW/

       function Category(id, categoryName, parentId){ this.id = id; this.categoryName = categoryName; this.parentId = parentId; } var categories = [ new Category(1, 'Root', 0), new Category(2, 'Cat1', 1), new Category(3, 'Cat2', 2), new Category(4, 'Cat3', 5), new Category(5, 'Cat4', 1), new Category(6, 'Cat5', 5), new Category(7, 'Cat6', 5), new Category(8, 'Cat7', 1), new Category(9, 'Cat8', 2), new Category(10, 'Cat9', 1), new Category(11, 'Cat10', 10), new Category(12, 'Cat11', 1), new Category(13, 'Cat12', 8) ]; categories.sort(function(a,b){ return a.parentId < b.parentId ? -1 : (a.parentId > b.parentId ? 1 : 0); }); var root = document.createElement('ul'), currentParentId=1, currentParentUl=root; for(var i=1; i < categories.length; ++i){ if(categories[i].parentId !== currentParentId){ currentParentId = categories[i].parentId; currentParentUl = document.createElement('ul'); root.getElementsByClassName('category_'+currentParentId)[0] .appendChild(currentParentUl); } currentParentUl.innerHTML += '
    • '+categories[i].categoryName+'
    • '; } document.body.appendChild(root);

      注1 :与@ DanielGimenez的代码一样,深度是无限的,父项必须在添加子项之前存在。

      注意2 :我的代码使用本机函数sortgetElementsByClassName来执行最昂贵的部分(排序和查找)以获得更好的性能。

      注3 :我使用了类而不是id来避免与页面的其他部分发生冲突。 但如果这不是问题,使用ID会提高速度。

      您可以在此处比较性能: http : //jsperf.com/creating-a-nested-list-with-an-object-array

      简短而又脏的jQuery。 这会破坏arrays。 效率不高,但很短。 http://jsfiddle.net/4JpsW/

       function drawList(cat) { r = $('
      ').attr('data-id', '1'); r.append($('
        ')); $('body').append(r) while (cat.length > 0) { if (cat[0].parent == 0) { cat.splice(0, 1); continue; } var i = 0; while ($('*[data-id=' + cat[i].parent + ']').length == 0) { i++; } elem = $('
      • ') .attr('data-id', cat[i].id) .text(cat[i].name); parent_elem = $('*[data-id=' + cat[i].parent + ']') if (parent_elem.find('>ul').length == 0) parent_elem.append($('
          ')); parent_elem.find('>ul').append(elem); cat.splice(i, 1); } }

          这是我使用的,有了它你可以有多个root父母。

          JS

            function loadCatList() { var li_str = ''; db.transaction(function (tx) { tx.executeSql('SELECT * FROM categories c,categories_description cd WHERE c.categories_id = cd.categories_id ORDER BY categories_id', [], function (tx, results) { var len = results.rows.length, i; var categories=[]; for (i = 0; i < len; i++) { var r = results.rows.item(i); categories[r.categories_id] = r; var catID = r.categories_id; } generate_tree_list=function(array, parent, level){ var has_children = false; for(key in array) { var value=array[key]; if (value['parent_id'] == parent) { if (has_children === false) { has_children = true; if(level === 0){ li_str += '
            '; }else{ li_str += '
          '; } generate_tree_list(categories,0,0); $('#parents').html(li_str); }); }); }

          HTML