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

Flo*_*ler 143 javascript dom

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

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

And*_*y E 230

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

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

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

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

if (document.querySelectorAll)
    var clsElements = document.querySelectorAll(".mySpeshalClass");
else
    // loop through all elements instead
Run Code Online (Sandbox Code Playgroud)

这肯定会加速现代浏览器的问题.


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

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

性能说明 - 尽力满足您的需求.通用选择器可以根据页面的复杂性返回大量节点.即使您确实需要查看某人可能看到的'body *'所有head内容,这意味着您可以使用选择器来删除所有内容.

  • 这个方法看起来很不错,但是如何在upper方法中选择一个元素呢?我只得到指数'我'? (2认同)
  • @Florian:就像你访问一个数组元素一样 - "all [i]`会给你当前的元素. (2认同)
  • 如何在循环中选择元素? (2认同)
  • @JesseAldridge:只是一种习惯/良好实践的力量.在每次迭代中避免属性查找通常都是微优化,但编写起来并不是特别困难,所以我只是自然而然地做到了. (2认同)
  • @Jonathan`getElementsByClassName()`的支持比`querySelectorAll()`更差(前者在IE 8中不受支持).OP明确表示他希望在页面上循环__all__元素,为此我给了他解决方案并提供了替代方案.我不确定那个问题是什么;-). (2认同)

tra*_*nal 33

一直在寻找相同的.好吧,不完全是.我只想列出所有DOM节点.

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

while(currentNode = ni.nextNode()) {
    console.log(currentNode.nodeName);
}
Run Code Online (Sandbox Code Playgroud)

要获取具有特定类的元素,我们可以使用过滤函数.

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);
}
Run Code Online (Sandbox Code Playgroud)

MDN上找到解决方案

  • 一个很酷的特性是节点迭代器还按照节点在 html 中出现的顺序遍历节点。我想知道某些 `document.body.getElementsByTagName('*')` 是否可以按乱序返回节点。 (2认同)

小智 9

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

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;
}
Run Code Online (Sandbox Code Playgroud)


Ily*_*man 7

一如既往,最好的解决方案是使用递归:

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]);
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

  • 使用递归的最佳时间是使用递归的最佳时间. (11认同)
  • "与`document.getElementsByTagName("*")相比,它创造了大约50%的节点;`" - 是的,它会找到[文本节点和注释节点以及元素节点](https://developer.mozilla .ORG/EN-US /文档/网络/ API /节点/节点类型).由于OP只询问元素,这是不必要的. (4认同)
  • 它_可能_在内存上更轻。根据您在每个递归级别中执行的操作,您可以在到达底部时构建一个非常大的调用堆栈。`NodeList` 只是引用已经在你的 DOM 中构建的 `Node`,所以它没有你想象的那么重。知道更多的人可以权衡,但我认为这只是一个内存参考大小,所以每个节点 8 个字节。 (2认同)

Mat*_*ius 6

对于那些使用 Jquery 的人

$("*").each(function(i,e){console.log(i+' '+e)});
Run Code Online (Sandbox Code Playgroud)


小智 5

Andy E.给出了很好的答案。

我想补充一下,如果您想要在某个特殊选择器中选择所有子级(这种需要最近发生在我身上),您可以在任何您想要的 DOM 对象上应用方法“getElementsByTagName()”。

例如,我需要解析网页的“视觉”部分,所以我做了这个

var visualDomElts = document.body.getElementsByTagName('*');
Run Code Online (Sandbox Code Playgroud)

这永远不会考虑头部。