Javascript: Làm thế nào để lặp qua TẤT CẢ các yếu tố DOM trên một trang?


155

Tôi đang cố gắng lặp lại TẤT CẢ các yếu tố trên một trang, vì vậy tôi muốn kiểm tra mọi yếu tố tồn tại trên trang này để tìm một lớp đặc biệt.

Vì vậy, làm thế nào để tôi nói rằng tôi muốn kiểm tra MỌI yếu tố?


1
bạn có chắc chắn muốn tự mình lặp lại mọi yếu tố không? tại sao không sử dụng jquery và bộ chọn để lấy các phần tử thuộc lớp cụ thể đó?
NG.

Không có phương thức document.getElementsByTagName sao?
SuperJedi224

* TL; DR: Đối với các yếu tố chỉ hiển thị, hãy sử dụng:document.body.getElementsByTagName('*')
Andrew

Lặp lại với:for (... of ...) { }
Andrew

Câu trả lời:


252

Bạn có thể truyền a *để getElementsByTagName()nó sẽ trả về tất cả các thành phần trong một trang:

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

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

Lưu ý rằng bạn có thể sử dụng querySelectorAll(), nếu có sẵn (IE9 +, CSS trong IE8), để chỉ tìm các phần tử với một lớp cụ thể.

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

Điều này chắc chắn sẽ tăng tốc các vấn đề cho các trình duyệt hiện đại.


Các trình duyệt hiện hỗ trợ foreach trên NodeList . Điều này có nghĩa là bạn có thể trực tiếp lặp các phần tử thay vì viết vòng lặp của riêng bạn.

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

Lưu ý về hiệu suất - Làm hết sức mình để phạm vi những gì bạn đang tìm kiếm. Một bộ chọn phổ quát có thể trả về rất nhiều nút tùy thuộc vào độ phức tạp của trang. Ngay cả khi bạn cần xem qua mọi thứ mà ai đó có thể thấy, điều đó có nghĩa là bạn có thể sử dụng 'body *'làm công cụ chọn để cắt tất cả headnội dung.


2
Phương pháp này có vẻ rất hay, nhưng làm thế nào tôi có thể chọn một phần tử trong phương thức trên? Tôi chỉ có chỉ số 'i'?
Florian Müller

2
@Florian: giống như bạn sẽ truy cập một phần tử mảng - all[i]sẽ cung cấp cho bạn phần tử hiện tại.
Andy E

2
Làm thế nào để chọn phần tử trong vòng lặp?
Debiprasad

2
@JesseAldridge: chỉ là một thói quen / thực hành tốt. Tránh tra cứu thuộc tính trên mỗi lần lặp thường là tối ưu hóa vi mô, nhưng nó không đặc biệt khó viết hơn và vì vậy tôi chỉ làm điều đó một cách tự nhiên.
Andy E

2
@Jonathan getElementsByClassName()có hỗ trợ tồi tệ hơn querySelectorAll()(trước đây không được hỗ trợ trong IE 8). OP tuyên bố rõ ràng rằng anh ấy muốn lặp lại tất cả các yếu tố trên một trang, mà tôi đã đưa cho anh ấy giải pháp và đưa ra một giải pháp thay thế. Tôi không chắc vấn đề là gì với điều đó ;-).
Andy E

38

Đã tìm kiếm cùng. Không hẳn là chính xác lắm. Tôi chỉ muốn liệt kê tất cả các Nút DOM.

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

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

Để có được các phần tử với một lớp cụ thể, chúng ta có thể sử dụng chức năng lọc.

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

Đã tìm thấy giải pháp trên MDN


không bao giờ thấy document.ceeateNodeIterator. Có vẻ thú vị về những tính năng mới mà JS mang lại;)
Florian Müller

2
Một tính năng thú vị của điều này là trình điều khiển nút cũng đi theo các nút theo thứ tự chúng xuất hiện trong html. Tôi tự hỏi nếu một số trong số document.body.getElementsByTagName('*')có thể trả lại các nút theo thứ tự xáo trộn.
Dân sự

Wow nó thực sự được hỗ trợ tốt!
rogerdpack

15

Như mọi khi giải pháp tốt nhất là sử dụng đệ quy:

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

Không giống như các đề xuất khác, giải pháp này không yêu cầu bạn tạo một mảng cho tất cả các nút, vì vậy nó sẽ nhẹ hơn trên bộ nhớ. Quan trọng hơn, nó tìm thấy nhiều kết quả hơn. Tôi không chắc những kết quả đó là gì, nhưng khi thử nghiệm trên chrome, nó tìm thấy nhiều hơn 50% nút so vớidocument.getElementsByTagName("*");


19
Thời gian tốt nhất để sử dụng đệ quy là thời gian tốt nhất để sử dụng đệ quy.
Adamlive

8
Nó đã tìm thấy nhiều hơn 50% các nút so với trước đây document.getElementsByTagName("*");- nó sẽ tìm thấy các nút văn bản và các nút nhận xét cũng như các nút phần tử . Vì OP chỉ hỏi về các yếu tố, điều đó không cần thiết.
Paul D. Chờ

1
thể nhẹ hơn trên bộ nhớ. Tùy thuộc vào mức độ bạn thực hiện trong mỗi cấp độ đệ quy, bạn có thể xây dựng một ngăn xếp cuộc gọi lớn có thể theo thời gian bạn đạt đến đáy. A NodeListchỉ đơn giản là tham chiếu các Nodes đã được xây dựng trong DOM của bạn, vì vậy nó không nặng như bạn tưởng tượng. Một người biết nhiều hơn có thể cân nhắc, nhưng tôi nghĩ đó chỉ là kích thước tham chiếu bộ nhớ, nên 8 byte cho mỗi nút.
Josh từ Qaribou

9

Đây là một ví dụ khác về cách bạn có thể lặp qua một tài liệu hoặc một phần tử:

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


3

Andy E. đã đưa ra một câu trả lời tốt.

Tôi sẽ thêm, nếu bạn cảm thấy chọn tất cả các con trong một số bộ chọn đặc biệt (nhu cầu này xảy ra với tôi gần đây), bạn có thể áp dụng phương thức "getElementsByTagName ()" trên bất kỳ đối tượng DOM nào bạn muốn.

Ví dụ, tôi chỉ cần phân tích phần "trực quan" của trang web, vì vậy tôi chỉ thực hiện điều này

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

Điều này sẽ không bao giờ xem xét phần đầu.


Thông minh! . . .
Andrew

2

từ liên kết này
tham khảo 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>

CẬP NHẬT: EDIT

kể từ câu trả lời cuối cùng của tôi, tôi đã tìm thấy giải pháp đơn giản hơn

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

    }

theo cuộc thảo luận SO này , document.allkhông được khuyến khích document.getElementBy*.
thejoshwolfe

@thejoshwolfe cảm ơn bạn nghĩ gì về giải pháp socond của tôi tôi đã cập nhật
shareef

0

Sử dụng *

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

0

tôi nghĩ rằng điều này thực sự nhanh chóng

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

0

Nhận tất cả các yếu tố bằng cách sử dụng var all = document.getElementsByTagName("*"); for (var i=0, max=all.length; i < max; i++);là ổn nếu bạn cần kiểm tra mọi yếu tố nhưng sẽ dẫn đến việc kiểm tra hoặc lặp lại các yếu tố hoặc văn bản lặp lại.

Dưới đây là một triển khai đệ quy kiểm tra hoặc lặp từng phần tử của tất cả các phần tử DOM chỉ một lần và chắp thêm:

(Tín dụng cho @George Reith cho câu trả lời đệ quy của anh ấy ở đây: Ánh xạ HTML sang 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);

}

-1

Bạn có thể thử với document.getElementsByClassName('special_class');


4
Phương pháp đúng là getElementsByClassName()và nó không được Internet Explorer hỗ trợ cho đến phiên bản 9.
Andy E
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.