Javascript:如何遍历页面上的所有 DOM 元素?

IT技术 javascript dom
2021-01-26 12:09:32

我试图遍历页面上的所有元素,所以我想检查此页面上存在的每个元素是否有一个特殊的类。

那么,我怎么说我想检查每个元素?

6个回答

您可以传递一个*togetElementsByTagName()以便它返回页面中的所有元素:

var all = document.getElementsByTagName("*");

for (var i=0, max=all.length; i < max; i++) {
     // Do something with the element here
}

请注意querySelectorAll(),如果可用(IE9+,IE8 中的 CSS),您可以使用来查找具有特定类的元素。

if (document.querySelectorAll)
    var clsElements = document.querySelectorAll(".mySpeshalClass");
else
    // loop through all elements instead

这肯定会加快现代浏览器的处理速度。


浏览器现在支持NodeList 上的 foreach这意味着您可以直接循环元素而不是编写自己的 for 循环。

document.querySelectorAll('*').forEach(function(node) {
    // Do whatever you want with the node object.
});

性能说明- 通过使用特定选择器,尽最大努力确定您要查找的范围。根据页面的复杂性,通用选择器可以返回大量节点。另外,当您不关心孩子,请考虑使用document.body.querySelectorAll代替document.querySelectorAll<head>

如何选择循环中的元素?
2021-03-18 12:09:32
@JesseAldridge:只是习惯/良好实践的力量。避免在每次迭代中查找属性通常是一种微优化,但编写起来并不是特别困难,所以我只是自然而然地这样做。
2021-03-24 12:09:32
@Jonathan 的getElementsByClassName()支持比querySelectorAll()(前者在 IE 8 中不受支持)更差OP 明确表示他想遍历页面上的所有元素,为此我给了他解决方案并提供了替代方案。我不确定这有什么问题;-)。
2021-03-28 12:09:32
这个方法看起来很不错,但是如何在upper方法中选择一个元素呢?我只有索引“i”?
2021-04-02 12:09:32
@Florian:就像您访问数组元素一样 -all[i]会给您当前元素。
2021-04-03 12:09:32

正在寻找相同的。嗯,不完全是。我只想列出所有 DOM 节点。

var currentNode,
    ni = document.createNodeIterator(document.documentElement, NodeFilter.SHOW_ELEMENT);

while(currentNode = ni.nextNode()) {
    console.log(currentNode.nodeName);
}

要获取具有特定类的元素,我们可以使用过滤器功能。

var currentNode,
    ni = document.createNodeIterator(
                     document.documentElement, 
                     NodeFilter.SHOW_ELEMENT,
                     function(node){
                         return node.classList.contains('toggleable') ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
                     }
         );

while(currentNode = ni.nextNode()) {
    console.log(currentNode.nodeName);
}

MDN上找到解决方案

从未见过 document.ceateNodeIterator。JS 带来的新特性似乎很有趣;)
2021-03-16 12:09:32
一个很酷的特性是节点迭代器还按照节点在 html 中出现的顺序遍历节点。我想知道其中的一些是否document.body.getElementsByTagName('*')可以按加扰顺序返回节点。
2021-04-07 12:09:32
哇它实际上得到了很好的支持!
2021-04-09 12:09:32

与往常一样,最好的解决方案是使用递归:

loop(document);
function loop(node){
    // do some thing with the node here
    var nodes = node.childNodes;
    for (var i = 0; i <nodes.length; i++){
        if(!nodes[i]){
            continue;
        }

        if(nodes[i].childNodes.length > 0){
            loop(nodes[i]);
        }
    }
}

与其他建议不同的是,此解决方案不需要您为所有节点创建一个数组,因此它更注重内存。更重要的是,它发现了更多的结果。我不确定这些结果是什么,但是在 chrome 上进行测试时,它发现与document.getElementsByTagName("*");

使用递归的最佳时机就是使用递归的最佳时机。
2021-03-15 12:09:32
可能是内存更轻。根据您在每个递归级别中执行的操作,您可以在到达底部时构建一个非常大的调用堆栈。ANodeList只是引用Node已在 DOM 中构建s,因此它没有您想象的那么重。知道更多的人可以权衡一下,但我认为这只是一个内存参考大小,所以每个节点 8 个字节。
2021-03-21 12:09:32
“与”相比,它发现了大约 50% 的节点document.getElementsByTagName("*");——是的,它会发现文本节点和评论节点以及元素节点由于 OP 只是询问元素,因此没有必要。
2021-03-25 12:09:32

这是关于如何遍历文档或元素的另一个示例:

function getNodeList(elem){
var l=new Array(elem),c=1,ret=new Array();
//This first loop will loop until the count var is stable//
for(var r=0;r<c;r++){
    //This loop will loop thru the child element list//
    for(var z=0;z<l[r].childNodes.length;z++){

         //Push the element to the return array.
        ret.push(l[r].childNodes[z]);

        if(l[r].childNodes[z].childNodes[0]){
            l.push(l[r].childNodes[z]);c++;
        }//IF           
    }//FOR
}//FOR
return ret;
}

对于那些使用 Jquery 的人

$("*").each(function(i,e){console.log(i+' '+e)});