在后序遍历中删除元素节点

时间:2014-02-02 23:58:36

标签: javascript jquery

说我有以下HTML(精简):

<div><div><div><ul><li>Text</li></ul></div></div></div>
<div><div><div><ul><li>Text 2</li></ul></div></div></div>
<div><div><div><ul><li>Text 3</li></ul></div></div></div>

我想首先删除最低的子元素,直到最终删除父元素,然后转到下一个父元素及其子元素。这可以通过一个简单的循环轻松完成,该循环遍历每个子元素,删除它,然后删除下一个子元素(即前一个子元素的父元素):

var children = $("body").find("*");
var i = children.length;
function loop() {
    $(children[i]).remove();
    i--;
    if (i > -1) {
        setTimeout(loop, 20);
    }
}
loop();

然而,问题在于它首先从最低的父元素中删除子元素。 If you were to run this code with my test markup,你可以看到我的意思。

我想从最顶层的父元素中删除子元素,然后向下工作,从而颠倒上述代码的顺序。我能够somewhat accomplish this with the following code

var parents = $("body").children(":not(:empty)");
var i = 0;
var speed = 1000;
function loop() {
    var children = $(parents[i]).find("*");
    var x = children.length;
    function inside() {
        $(children[x]).remove();
        x--;
        if (x > -1) {
            setTimeout(inside, speed);
        } else if (i < parents.length) {
            $(parents[i - 1]).remove();
            loop();
        } else if (i === parents.length) {
            $(parents[i - 1]).remove();
        }
    }
    inside();
    i++;
}
loop();

但是,此代码的问题在于它只反转了相对于父元素的删除顺序。 If there are multiple child elements within a parent, it will still delete them in the default ascending order (bottom to top)

因此,我的问题是,如何以更清晰的方式删除所有元素,无论有多少子元素,都按降序删除?必须有比我尝试的更好的方法。 jQuery也不是必需的。 setTimeout s的原因是因为我需要在删除元素之间有一个延迟。像往常一样,我可能忽略了一些相对简单的事情,所以请耐心等待。

重申一下,如果HTML看起来像这样:

<div>
    <div>Child 1</div>
    <div>Child 2</div>
    <div>
        <div>Child 3</div>
        <div>Child 4</div>
    </div>
</div>

我希望按以下顺序删除它:

  1. 儿童1
  2. Child 2
  3. 儿童3
  4. Child 4

4 个答案:

答案 0 :(得分:2)

伪代码中的算法思想:

RemoveNode( node) { 
for(i=node.children.length-1;i>=0;i--){
    RemoveNode(node.children[i]);
}
remove(self);
return;
}

根据伪代码添加实际代码:

function RemoveNode(node){
    for(var i = node.children.length - 1; i >= 0; i--){
        RemoveNode(node.children[i]);
    }
    $(node).remove();
}

带有中断的伪代码,看看算法是如何工作的。不明白为什么,但我不能让它延迟工作。

function RemoveNode(node){
    for(var i = node.children.length - 1; i >= 0; i--){
      RemoveNode(node.children[i]);
        alert("hi");
    }
    $(node).remove();
}

RemoveNode($(".parent")[0]);

答案 1 :(得分:2)

首先使用以下递归函数构建DOM树的后序(aka child first)版本:

var nodes = [];

function generate()
{
    $(this).children().each(generate);
    nodes.push(this);
}

generate.call($('body'));

然后,按照正常情况进行迭代:

var i = 0;

function loop() 
{
    $(nodes[i]).remove();
    if (++i < nodes.length) {
        setTimeout(loop, 1000);
    }
}

loop();

Demo

答案 2 :(得分:1)

我认为这可以满足您的需求:

removeLast();

function removeLast(){
    var o = document.getElementById("root"), p = o;
    while (p.lastChild) p = p.lastChild;
    p.parentNode.removeChild(p);
    if(o != p) setTimeout(removeLast,20);
}

Fiddle

答案 3 :(得分:0)

我不确定我完全理解这个问题,但也许这就是你要找的东西?

演示:http://jsfiddle.net/xT3Au/1/

var $parents = $('.parent');

$parents.each(function(i) {
    var $tree = $(this).find('*').addBack();
    $tree.sort(function(a, b) {
        return $(a).find('*').length - $(b).find('*').length;
    }).each(function(j, el) {
        var speed = 1000 * (j + 1 + i * $tree.length);
        setTimeout(function(){ $(el).remove() }, speed);
    });
});

我认为使用课程来了解哪些家长应该遵循哪种顺序会更容易。否则很难弄清楚订单。如果我弄错了,请尝试使用排序功能。