Javascript: Bir sayfadaki TÜM DOM öğeleri arasında nasıl döngü yapılır?


156

Ben bir sayfada TÜM öğeleri üzerinde döngü çalışıyorum, bu yüzden bu sayfada mevcut her öğeyi özel bir sınıf için kontrol etmek istiyorum.

Peki, HER öğeyi kontrol etmek istediğimi nasıl söyleyebilirim?


1
her öğeyi kendiniz gözden geçirmek istediğinizden emin misiniz? neden belirli bir sınıftaki öğeleri kapmak için jquery ve seçicileri kullanmıyorsunuz?
NG.

Bir document.getElementsByTagName yöntemi yok mu?
SuperJedi224

* TL; DR: Yalnızca görünür öğeler için şunları kullanın:document.body.getElementsByTagName('*')
Andrew

İterat ile:for (... of ...) { }
Andrew

Yanıtlar:


252

Birini, bir sayfadaki tüm öğeleri döndürmesi *için iletebilirsiniz getElementsByTagName():

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

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

Kullanmak ki Not querySelectorAll()Sunulursa, (IE9 + IE8'de, CSS) sadece belirli bir sınıfla unsurları bulmak için.

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

Bu kesinlikle modern tarayıcılar için işleri hızlandıracaktır.


Tarayıcılar artık NodeList'te foreach'i destekliyor . Bu, döngüye kendi yazmak yerine öğeleri doğrudan döngüye alabileceğiniz anlamına gelir.

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

Performans notu - Aradığınızı kapsamak için elinizden geleni yapın. Evrensel bir seçici, sayfanın karmaşıklığına bağlı olarak çok sayıda düğüm döndürebilir. Birisinin görebileceği her şeye bakmanız gerekse bile, bu, 'body *'tüm headiçeriği kesmek için seçici olarak kullanabileceğiniz anlamına gelir .


2
Bu yöntem çok hoş görünüyor, ancak üst yöntemde bir öğeyi nasıl seçebilirim? Sadece 'i' indeksini aldım?
Florian Müller

2
@Florian: bir dizi öğesine erişeceğiniz gibi - all[i]size geçerli öğeyi verir.
Andy E

2
Döngüdeki elemanı nasıl seçebilirim?
Debiprasad

2
@ JesseAldridge: sadece alışkanlık / iyi uygulama gücü. Her yinelemede özellik aramasından kaçınmak genellikle bir mikro optimizasyondur, ancak yazmak özellikle daha zor değildir ve bu yüzden doğal olarak yaparım.
Andy E

2
@Jonathan getElementsByClassName()daha kötü desteğe sahiptir querySelectorAll()(eski IE 8'de desteklenmez). OP , bir sayfadaki tüm öğelerin üzerinden geçmek istediğini belirtti, bunun için ona çözüm verdim ve bir alternatif sundum. Bu sorunun nasıl olduğundan emin değilim ;-).
Andy E

39

Aynı arıyordu. Tam olarak değil. Yalnızca tüm DOM Düğümlerini listelemek istedim.

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

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

Belirli bir sınıfa sahip öğeleri almak için filtre işlevini kullanabiliriz.

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

Bulunan çözelti MDN


hiç görmedim document.ceeateNodeIterator. JS'nin getirdiği yeni özellikler ilginç görünüyor;)
Florian Müller

2
Bunun harika bir özelliği, düğümün ayrıca düğümleri html'de göründükleri sırayla yürümesidir. Bazılarının document.body.getElementsByTagName('*')düğümleri şifreli sırayla geri getirip getiremeyeceğini merak ediyorum .
Sivil

Vay be aslında iyi destekleniyor!
rogerdpack

15

Her zaman olduğu gibi en iyi çözüm özyineleme kullanmaktır:

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

Diğer önerilerin aksine, bu çözüm tüm düğümler için bir dizi oluşturmanızı gerektirmez, bu nedenle bellekte daha fazla ışık olur. Daha da önemlisi, daha fazla sonuç bulur. Bu sonuçların ne olduğundan emin değilim, ancak krom üzerinde test yaparken kıyasla% 50 daha fazla düğüm bulurdocument.getElementsByTagName("*");


19
Özyineleme kullanmak için en iyi zaman özyineleme kullanmak için en iyi zamandır.
Adamlive

8
“İle karşılaştırıldığında yaklaşık% 50 daha fazla düğüm document.getElementsByTagName("*");bulur” - evet, metin düğümleri ve yorum düğümleri ile öğe düğümlerini bulur . OP sadece unsurları sorduğundan, bu gereksizdir.
Paul

1
Bu belki belleğe daha hafif. Her özyineleme düzeyinde ne kadar yaptığınıza bağlı olarak, en alt seviyeye geldiğinizde büyük bir çağrı yığını oluşturabilirsiniz. A NodeList, DOM'nizde Nodezaten oluşturulmuş olanlara atıfta bulunuyor, bu yüzden hayal edebileceğiniz kadar ağır değil. Daha fazlasını bilen biri tartabilir, ancak bence bu sadece bir bellek referans boyutu, bu yüzden düğüm başına 8 bayt.
Qaribou'dan Josh

9

Bir belgede veya öğede nasıl döngü oluşturabileceğinizle ilgili başka bir örnek:

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. iyi bir cevap verdi.

Eklerim, bazı özel seçicilerdeki tüm alt öğeleri seçmek istiyorsanız (bu son zamanlarda başıma geldi), istediğiniz herhangi bir DOM nesnesine "getElementsByTagName ()" yöntemini uygulayabilirsiniz.

Bir örnek olarak, sadece web sayfasının "görsel" bölümünü ayrıştırmam gerekiyordu, bu yüzden bunu yaptım

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

Bu, baş kısmı asla dikkate almayacaktır.


Mükemmel! . . .
Andrew

2

bu linkten
javascript referansı

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

GÜNCELLEME: DÜZENLEME

son cevabımdan beri daha basit bir çözüm buldum

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

    }

göre bu SO tartışma , document.alllehine önerilmez document.getElementBy*.
thejoshwolfe

@thejoshwolfe i güncellenen benim notENTER çözümün düşünüyorum ne teşekkür
shareef

0

kullanım *

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

0

bence bu gerçekten hızlı

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

0

var all = document.getElementsByTagName("*"); for (var i=0, max=all.length; i < max; i++);Her öğeyi kontrol etmeniz gerekiyorsa, yinelenen öğelerin veya metnin denetlenmesine veya döngüye girmesine neden olacaksa, tüm öğelerin kullanılması tamamdır.

Aşağıda, tüm DOM öğelerinin her bir öğesini yalnızca bir kez kontrol eden ve ekleyen bir özyineleme uygulaması verilmiştir :

(@George Reith'e verilen krediler, özyineleme cevabı için: HTML'yi JSON ile eşleştirin )

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

İle deneyebilirsiniz document.getElementsByClassName('special_class');


4
Doğru yöntem getElementsByClassName()9 sürümüne kadar Internet Explorer tarafından desteklenmez.
Andy E
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.