循环遍历div的所有后代 - 仅限JS

时间:2013-07-23 21:41:15

标签: javascript optimization

我一直在使用jQuery来执行此操作:

$element.find("*").each(function() {
    var $this = $(this);

    $this.removeAttr("style width align");

    if ($this.is("embed")) {
        $element.append("<div class='video'></div>");
        $this.attr("width", 640).attr("height", 360).parent().appendTo("#" + element + " .video");
    };
});

但我一直在读,与简单的for循环(jsPerf)相比,jQuery的.each()方法相当慢。我的问题是如何用纯JS模仿这个?找到div中的所有元素,然后遍历节点。

我试图搜索这个,但我似乎找到的只是jQuery答案 - 无处不在。

我尝试了其他的东西,但这跟我选择所有后代一样接近:

var children = document.getElementById('id').getElementsByTagName('*');

for( var i = 0; i<children.lengtth; i++){
    children[i].removeAttribute("style");
    console.log(children[i]);
}

4 个答案:

答案 0 :(得分:27)

你已经做得对了

var ancestor = document.getElementById('id'),
    descendents = ancestor.getElementsByTagName('*');
    // gets all descendent of ancestor

现在你只需要循环children

var i, e, d;
for (i = 0; i < descendents.length; ++i) {
    e = descendents[i];
    e.removeAttribute('style');
    e.removeAttribute('width');
    e.removeAttribute('align');
    if (e.tagName === 'EMBED') {
        d = document.createElement('div');
        d.setAttribute('class', 'video');
        ancestor.appendChild(d);
    }
}

根据您正在做的事情,因为您使用getElementsByTagName获取descendentsdescendents直播 NodeList ,因此当您向ancestor添加更多节点时,它的长度会发生变化。如果您需要避免这种情况,请在循环

之前将其转换为数组
decendents = Array.prototype.slice.call(decendents);

有关可重复使用的功能,请参阅this gist

答案 1 :(得分:3)

你能用这么简单的东西吗?

    // get a handle to the div you want.
var div = document.getElementById('someID'),
    // get an array of child nodes
    divChildren = div.childNodes;

for (var i=0; i<divChildren.length; i++) {
    divChildren[i].style.width = null;
    divChildren[i].style.textAlign = null;
}

答案 2 :(得分:2)

我在@Paul S.的回答中评论说,您也可以克隆节点并使用文档片段添加新的嵌入。这是一个例子:

<强> HTML:

<div>
    <div id="container">
        <div align="right">child</div>
        <div align="center">child</div>
        <embed src="" width="0" height="0" />
        <div align="center">child</div>
        <div style="width: 40px">child</div>
        <div style="font-size: 100px">child</div>
        <div width="60%">child</div>
        <embed src="" width="0" height="0"/>
        <div width="60%">child</div>
    </div>
</div>

<强> JS:

var elm,
    clone,
    doc,
    next,
    fragment,
    live = document.getElementById("container");

if (live !== null) {
    fragment = document.createDocumentFragment();
    clone = live.cloneNode(true);
    next = clone.firstChild;
    while(next !== null) {
        if (next.nodeName !== "#text") {
            next.removeAttribute('style');
            next.removeAttribute('width');
            next.removeAttribute('align');

            if (next.tagName === 'EMBED') {
                doc = document.createElement('div');
                doc.setAttribute('class', 'video');
                doc.innerHTML = "EMBED detected, adding div...";
                fragment.appendChild(doc);
            }
        }
        next = next.nextSibling;
    }
    clone.appendChild(fragment);
    live.parentNode.replaceChild(clone, live);
}

您可以看到演示here.

克隆节点会阻止DOM的实时修改,因为style属性可能具有导致浏览器多次重绘的属性。

答案 3 :(得分:2)

您可以将querySelectorAll用于每个函数。

document.querySelectorAll('li').forEach(function(element) {
    console.log(element);
});