如何循环遍历页面上的所有 DOM 元素?

问题描述 投票:0回答:13

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

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

javascript dom
13个回答
329
投票

您可以将

*
传递给
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

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


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

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

性能说明 - 尽最大努力使用特定选择器来确定您要查找的内容。通用选择器可以根据页面的复杂性返回大量节点。另外,当您不关心

document.body.querySelectorAll
孩子时,请考虑使用
document.querySelectorAll
代替
<head>


50
投票

正在寻找相同的。嗯,不完全是。我只想列出所有 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


19
投票

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

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%

11
投票

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

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

6
投票

对于那些使用Jquery的人

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

5
投票

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

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

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

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

这永远不会考虑头部。


3
投票

从此链接
javascript 参考

<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

    }

2
投票

如果您需要检查每个元素,使用

var all = document.getElementsByTagName("*"); for (var i=0, max=all.length; i < max; i++);
获取所有元素是可以的,但会导致检查或循环重复元素或文本。

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

(感谢 @George Reith 的递归答案: 将 HTML 映射到 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);

}

0
投票

使用

*

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

0
投票

我觉得这真的很快

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

0
投票

这就是如何使黑白模式循环遍历所有元素

var all = document.getElementsByTagName("*");
for (var i=0, max=all.length; i < max; i++) {
     all[i].style.backgroundColor  = 'black';
     all[i].style.color  = 'white';
}

0
投票

Ilya Gazman 的解决方案由于某种原因不会添加没有子节点的节点。所以这里是固定的、完整的代码,您可以搜索(不过,您自己编写它很容易):

var output = [];
loop(document);
function loop(node){
    // do some thing with the node here, for example
    output[output.length] = node;

    var nodes = node.childNodes;
    for (var i = 0; i <nodes.length; i++){
        // What is it?
        //if(!nodes[i]){
        //    continue;
        //}

        if(nodes[i].childNodes.length > 0){
            loop(nodes[i]);
        }
        else
             output[output.length] = nodes[i];
    }
}
// output has the result

P.S.:原作者可能想对没有子节点的节点调用递归

loop
,但是为此目的设计了检查,上面标记为“这是什么?”,但没有结束。

P.P.S.:是的

querySelectorAll
getElementsByTagName
由于某种原因不会返回所有元素。可能文档解释了原因。


-2
投票

您可以尝试使用

document.getElementsByClassName('special_class');

© www.soinside.com 2019 - 2024. All rights reserved.