【问题标题】:How can I loop through ALL DOM elements on a page?如何循环浏览页面上的所有 DOM 元素?
【发布时间】:2011-05-14 11:15:37
【问题描述】:

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

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

【问题讨论】:

  • 您确定要自己循环遍历每个元素吗?为什么不使用 jquery 和选择器来抓取属于该特定类的元素?
  • 不是有document.getElementsByTagName方法吗?
  • *TL;DR: 对于仅可见元素,请使用:document.body.getElementsByTagName('*')
  • 迭代:for (... of ...) { }
  • 我用过:Array.from(document.querySelectorAll('*')).forEach(el => {})

标签: javascript dom


【解决方案1】:

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

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

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

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

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

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


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

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

性能说明 - 使用特定的选择器尽最大努力确定要查找的范围。通用选择器可以根据页面的复杂性返回许多节点。此外,如果您不关心 &lt;head&gt; 孩子,请考虑使用 document.body.querySelectorAll 而不是 document.querySelectorAll

【讨论】:

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

正在寻找相同的。嗯,不完全是。我只想列出所有 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.ceeateNodeIterator。 JS 带来了什么新功能似乎很有趣;)
  • 一个很酷的特性是节点迭代器还按照它们在 html 中出现的顺序遍历节点。我想知道document.body.getElementsByTagName('*') 中的一些是否可以按乱序返回节点。
  • 哇,它实际上得到了很好的支持!
【解决方案3】:

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

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("*");相比,节点多出约 50%@

【讨论】:

  • 使用递归的最佳时机就是使用递归的最佳时机。
  • “与document.getElementsByTagName("*");相比,它发现了大约50%的节点”——是的,它会找到text nodes and comment nodes as well as element nodes。由于 OP 只是询问元素,因此没有必要。
  • 可能在内存上更轻。根据你在每一级递归中做了多少,当你到达底部时,你可以构建一个非常大的调用堆栈。 NodeList 只是引用了已经在你的 DOM 中构建的 Nodes,所以它没有你想象的那么重。知道更多的人可以权衡一下,但我认为这只是内存参考大小,因此每个节点 8 个字节。
【解决方案4】:

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

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;
}

【讨论】:

    【解决方案5】:

    对于那些正在使用 Jquery 的人

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

    【讨论】:

      【解决方案6】:

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

      我要补充的是,如果你想在某个特殊的选择器中选择所有子元素(我最近遇到了这种需要),你可以在任何你想要的 DOM 对象上应用方法“getElementsByTagName()”。

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

      var visualDomElts = document.body.getElementsByTagName('*');
      

      这永远不会考虑头部。

      【讨论】:

        【解决方案7】:

        来自此链接
        javascript reference

        <html>
        <head>
        <title>A Simple Page</title>
        <script language="JavaScript">
        <!--
        function findhead1()
        {
            var tag, tags;
            // or you can use var allElem=document.all; and loop on it
            tags = "The tags in the page are:"
            for(i = 0; i < document.all.length; i++)
            {
                tag = document.all(i).tagName;
                tags = tags + "\r" + tag;
            }
            document.write(tags);
        }
        
        //  -->
        </script>
        </head>
        <body onload="findhead1()">
        <h1>Heading One</h1>
        </body>
        </html>
        

        更新:编辑

        自从我上次回答以来,我找到了更好更简单的解决方案

        function search(tableEvent)
            {
                clearResults()
        
                document.getElementById('loading').style.display = 'block';
        
                var params = 'formAction=SearchStocks';
        
                var elemArray = document.mainForm.elements;
                for (var i = 0; i < elemArray.length;i++)
                {
                    var element = elemArray[i];
        
                    var elementName= element.name;
                    if(elementName=='formAction')
                        continue;
                    params += '&' + elementName+'='+ encodeURIComponent(element.value);
        
                }
        
                params += '&tableEvent=' + tableEvent;
        
        
                createXmlHttpObject();
        
                sendRequestPost(http_request,'Controller',false,params);
        
                prepareUpdateTableContents();//function js to handle the response out of scope for this question
        
            }
        

        【讨论】:

        • 根据this SO discussion,不鼓励document.all 支持document.getElementBy*
        • @thejoshwolfe 感谢您对我更新的 socond 解决方案有何看法
        【解决方案8】:

        使用*

        var allElem = document.getElementsByTagName("*");
        for (var i = 0; i < allElem.length; i++) {
            // Do something with all element here
        }
        

        【讨论】:

          【解决方案9】:

          我认为这真的很快

          document.querySelectorAll('body,body *').forEach(function(e) {
          

          【讨论】:

            【解决方案10】:

            如果您需要检查每个元素,则可以使用 var all = document.getElementsByTagName("*"); for (var i=0, max=all.length; i &lt; max; i++); 获取所有元素,但会导致检查或循环重复元素或文本。

            下面是一个递归实现,它只检查或循环所有DOM元素的每个元素一次并追加:

            (感谢@George Reith 在这里的递归答案: Map HTML to JSON

            function mapDOMCheck(html_string, json) {
              treeObject = {}
            
              dom = new jsdom.JSDOM(html_string) // use jsdom because DOMParser does not provide client-side Window for element access
              document = dom.window.document
              element = document.querySelector('html')
            
              // Recurse and loop through DOM elements only once
              function treeHTML(element, object) {
                var nodeList = element.childNodes;
            
                if (nodeList != null) {
                  if (nodeList.length) {
                    object[element.nodeName] = []; // IMPT: empty [] array for parent node to push non-text recursivable elements (see below)
            
                    for (var i = 0; i < nodeList.length; i++) {
                      console.log("nodeName", nodeList[i].nodeName);
            
                      if (nodeList[i].nodeType == 3) { // if child node is **final base-case** text node
                        console.log("nodeValue", nodeList[i].nodeValue);
                      } else { // else
                        object[element.nodeName].push({}); // push {} into empty [] array where {} for recursivable elements
                        treeHTML(nodeList[i], object[element.nodeName][object[element.nodeName].length - 1]);
                      }
                    }
                  }
                }
              }
            
              treeHTML(element, treeObject);
            
            }
            

            【讨论】:

              【解决方案11】:

              你可以试试 document.getElementsByClassName('special_class');

              【讨论】:

              • 正确的方法是getElementsByClassName(),Internet Explorer 9 及以下版本不支持。
              猜你喜欢
              • 1970-01-01
              • 2010-09-10
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-12-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多