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はこれでOKです。

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'));

jsフィドル

于 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 : 私のコードはネイティブ関数sortを使用getElementsByClassNameし、最もコストのかかる部分 (並べ替えと検索) を実行してパフォーマンスを向上させています。

注 3 : ページの他の部分との競合を避けるために、ID の代わりにクラスを使用しました。しかし、それが問題でなければ、id を使用すると速度が向上します。

ここでパフォーマンスを比較できます: http://jsperf.com/creating-a-nested-list-with-an-object-array

于 2013-07-26T00:16:31.370 に答える