6

我有一组经常更改的 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

4 回答 4

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

于 2013-07-26T00:22:12.880 回答
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

于 2013-07-26T00:16:31.370 回答
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);
  }
}
于 2013-07-26T00:56:12.980 回答
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>
于 2014-02-02T18:26:05.890 回答