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

时间:2013-07-25 23:41:52

标签: javascript jquery

我有一组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)
]

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

<ul>
<li>Cat1
    <ul>
        <li>Cat2</li>
        <li>Cat8</li>
    </ul>

<li>Cat4
    <ul>
        <li>Cat3</li>
        <li>Cat5</li>
        <li>Cat6</li>
    </ul>
</li>
<li>Cat7
    <ul>
        <li>Cat12</li>
    </ul>
</li>
<li>Cat8</li>
<li>Cat9
    <ul>
        <li>Cat10</li>
    </ul>
</li>
<li>Cat11</li>
</ul>

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

jQuery对此很好。

4 个答案:

答案 0 :(得分:3)

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

// 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 = $('<li>' + this.name + '</li>').appendTo($parentElem);
    if (this.children.length) {
        this.renderChildren($('<ul />').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

答案 1 :(得分:2)

演示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 += '<li class="category_'+categories[i].id+'">'+categories[i].categoryName+'</li>';
}
document.body.appendChild(root);

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

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

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

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

答案 2 :(得分:0)

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

function drawList(cat) {
  r = $('<div></div>').attr('data-id', '1');
  r.append($('<ul></ul>'));
  $('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 = $('<li></li>')
      .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($('<ul></ul>'));

    parent_elem.find('>ul').append(elem);

    cat.splice(i, 1);
  }
}

答案 3 :(得分:0)

这就是我使用的东西,你可以拥有多个根父母。

<强> 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 += '<ul>';

 }else{

 li_str += '<ul>';

 }

 level++;

 }
 li_str += '<li id="'+ value['categories_id'] +'"><a href="productsList.html?cPath='+ value['categories_id'] +'"  data-ajax="false"><h3>' + value['categories_name'] + '</h3><p>' + value['categories_image'] + '</p></a>'

 generate_tree_list(array, key, level); 

 li_str += '</li>';

 }

 }

if (has_children === true) li_str += '</ul>';

}
generate_tree_list(categories,0,0);
$('#parents').html(li_str);





});

});  

}

<强> HTML

<div id="catItems"><script>loadCatList();</script>

 <div id="parents"></div>