4

我正在使用一个具有这种疯狂 for 循环的项目来扩展 D3.js 画布交互中的节点。本质上,我想要的是扩展所有孩子。因此,如果一个对象有一个孩子,我想扩展它们。

我从中剪掉了一大段代码。有这么多 for 循环,这很荒谬。我怎样才能将其简化为简单的“查找所有孩子,预制切换();和更新();”?

$('.expandAll').click(function(e) {
    e.preventDefault();
    length = root.children.length;

    for (var i = 0; i < length; i++) {
        toggle(root.children[i]);
        update(root);

        if (root.children[i]['children']) {
            childlength = root.children[i]['children'].length;

            for (var j = 0; j < childlength; j++) {
                toggle(root.children[i]['children'][j]);
                update(root);

                if (root.children[i]['children'][j]['children']) {
                    childlength2 = root.children[i]['children'][j]['children'].length;

                    for (var k = 0; k < childlength2; k++) {
                        toggle(root.children[i]['children'][j]['children'][k]);
                        update(root);
                    }
                }
            }
        }
    }
});
4

3 回答 3

3

听起来像是递归的好例子:

$('.expandAll').click(function(e) {
    e.preventDefault();

    expandAll(root);
});

var expandAll = function (node) {
    toggle(node);
    update(node);

    // edit: if nodes with no children are lacking the children property
    if (!node.children) {
        return;
    }

    for (var i = 0, length = node.children.length; i < length; i++) {
        expandAll(node.children[i]);
    }
};

我不确定是什么toggle以及update确切的含义,但是您可以update在调用expandAll(root);.

于 2013-07-19T15:28:28.733 回答
0

使用递归!如果您只需要支持三个级别,您可以为此引入一个计数器变量。

$('.expandAll').click(function(e) {
    e.preventDefault();
    expandAll(root, root.children/*, 3*/);
}
function expandAll(root, children/*, lev*/) {
    if (!children/* || lev<=0 */) return;
    var length = children.length;
    for (var i = 0; i < length; i++) {
         toggle(children[i]);
         update(root);
         expandAll(root, children[i].children/*, lev-1*/);
    }
}

顺便说一句,你确定你需要updateroot每首歌之后打电话toggle吗?当所有孩子都被切换时,最后调用一次对我来说更有意义。

于 2013-07-19T15:29:23.060 回答
0

不确定这是否有帮助,但我一直在用嵌套对象做一些事情:

object = {
    children: [], // array of similar objects with children property and update function
    update: function(data){
        // update this item
        this.data = data;

        // update each immediate child
        if (this.children)
            for (var i in this.children)
                this.children[i].update(data);
    }
};

// then you just call update on the first item:
object.update(data);

如果您遵循这种模式,而不是在根级别设置复杂的循环,您只需遍历直接子级并调用它们的更新函数,然后循环遍历它们的子级,并一直向下。

我不是一个出色的 JS 开发人员,只是我为前几天正在处理的一些嵌套评论做的事情;)

于 2013-07-19T15:33:42.127 回答