2013-07-23 33 views
13

JS Tôi đã sử dụng jQuery để làm điều này:Vòng qua tất cả hậu duệ của một div - chỉ

$element.find("*").each(function() { 
    var $this = $(this); 

    $this.removeAttr("style width align"); 

    if ($this.is("embed")) { 
     $element.append("<div class='video'></div>"); 
     $this.attr("width", 640).attr("height", 360).parent().appendTo("#" + element + " .video"); 
    }; 
}); 

Nhưng tôi đã đọc rằng phương pháp .each() jQuery là khá chậm khi so sánh với một đơn giản cho vòng lặp (jsPerf). Câu hỏi của tôi là làm thế nào tôi có thể bắt chước điều này với JS thuần túy? Tìm tất cả các phần tử trong một div, sau đó lặp qua các nút.

Tôi đã cố gắng tìm kiếm điều này nhưng tất cả những gì tôi có thể tìm thấy là câu trả lời jQuery - ở mọi nơi.

Tôi đã thử những thứ khác nhưng điều này là càng gần như tôi phải chọn tất cả con cháu:

var children = document.getElementById('id').getElementsByTagName('*'); 

for(var i = 0; i<children.lengtth; i++){ 
    children[i].removeAttribute("style"); 
    console.log(children[i]); 
} 
+0

lý do cho sự tồn tại của jquery là chính xác này ... nó có thể chậm hơn (cách chăm sóc ...) nhưng nó sẽ làm việc trên tất cả các trình duyệt ... bạn có thực sự muốn lặp dom cây và làm cho nó hoạt động trong tất cả các trình duyệt? – Rufinus

+0

[] .slice.call (elm.children) cung cấp cho bạn một mảng các phần tử con, trong khi [] .slice.call (elm.childNodes) bao gồm các nút văn bản.getElementsByTagName() sẽ đi sâu hơn so với trẻ em trực tiếp, nếu đó là những gì bạn muốn. – dandavis

+1

Có vấn đề gì với giải pháp vanilla JS của bạn? –

Trả lời

19

Bạn đã làm đúng

var ancestor = document.getElementById('id'), 
    descendents = ancestor.getElementsByTagName('*'); 
    // gets all descendent of ancestor 

Bây giờ bạn chỉ cần để lặp trên children

var i, e, d; 
for (i = 0; i < descendents.length; ++i) { 
    e = descendents[i]; 
    e.removeAttribute('style'); 
    e.removeAttribute('width'); 
    e.removeAttribute('align'); 
    if (e.tagName === 'EMBED') { 
     d = document.createElement('div'); 
     d.setAttribute('class', 'video'); 
     ancestor.appendChild(d); 
    } 
} 

Tùy thuộc vào những gì bạn đang làm, bởi vì bạn đang sử dụng getElementsByTagName để có được descendents, descendents là một sốngNodeList, vì vậy nó là chiều dài sẽ thay đổi khi bạn thêm Nodes-ancestor. Nếu bạn cần phải tránh điều này, chuyển nó sang một Mảng trước khi vòng lặp

decendents = Array.prototype.slice.call(decendents); 

Xem this gist cho một chức năng tái sử dụng.

+0

LOL câu trả lời của tôi là (là: P) pratically giống hệt của bạn –

+0

@LightStyle ngoại trừ tôi chứa 'i'mprovised' e'xplosive 'd'evice 8-) –

+0

Vì đó là danh sách trực tiếp, tôi có phải chuyển đổi thành mảng không hoặc tôi có thể tiết kiệm thời gian chỉ trong thời gian khi tôi sẽ bắt đầu lặp? –

3

bạn có thể sử dụng một cái gì đó đơn giản như thế này không?

// get a handle to the div you want. 
var div = document.getElementById('someID'), 
    // get an array of child nodes 
    divChildren = div.childNodes; 

for (var i=0; i<divChildren.length; i++) { 
    divChildren[i].style.width = null; 
    divChildren[i].style.textAlign = null; 
} 
2

Tôi đã nhận xét câu trả lời của @Paul S. rằng bạn cũng có thể sao chép nút và sử dụng đoạn tài liệu để thêm nhúng mới. Dưới đây là một ví dụ:

HTML:

<div> 
    <div id="container"> 
     <div align="right">child</div> 
     <div align="center">child</div> 
     <embed src="" width="0" height="0" /> 
     <div align="center">child</div> 
     <div style="width: 40px">child</div> 
     <div style="font-size: 100px">child</div> 
     <div width="60%">child</div> 
     <embed src="" width="0" height="0"/> 
     <div width="60%">child</div> 
    </div> 
</div> 

JS:

var elm, 
    clone, 
    doc, 
    next, 
    fragment, 
    live = document.getElementById("container"); 

if (live !== null) { 
    fragment = document.createDocumentFragment(); 
    clone = live.cloneNode(true); 
    next = clone.firstChild; 
    while(next !== null) { 
     if (next.nodeName !== "#text") { 
      next.removeAttribute('style'); 
      next.removeAttribute('width'); 
      next.removeAttribute('align'); 

      if (next.tagName === 'EMBED') { 
       doc = document.createElement('div'); 
       doc.setAttribute('class', 'video'); 
       doc.innerHTML = "EMBED detected, adding div..."; 
       fragment.appendChild(doc); 
      } 
     } 
     next = next.nextSibling; 
    } 
    clone.appendChild(fragment); 
    live.parentNode.replaceChild(clone, live); 
} 

Bạn có thể xem bản demo here.

Nhân bản các nút ngăn chặn sự biến đổi trực tiếp của DOM vì thuộc tính kiểu có thể có các thuộc tính khiến trình duyệt quay lại sơn nhiều lần.

1

Bạn có thể sử dụng chức năng querySelectorAll's forEach.

document.querySelectorAll('li').forEach(function(element) { 
    console.log(element); 
}); 
Các vấn đề liên quan