Петля через всех потомков div-JS
Я использую jQuery для этого:
$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");
};
});
Но я читал, что метод jQuery .each()
довольно медленный по сравнению с простым циклом цикла (jsPerf). Мой вопрос: как я могу имитировать это с помощью чистого JS? Найдите все элементы внутри div
, затем прокрутите узлы.
Я пытался найти это, но все, что я могу найти, это ответы jQuery - везде.
Я пробовал другие вещи, но это было как можно ближе к выбору всех потомков:
var children = document.getElementById('id').getElementsByTagName('*');
for( var i = 0; i<children.lengtth; i++){
children[i].removeAttribute("style");
console.log(children[i]);
}
Ответы
Ответ 1
Вы уже делаете это правильно
var ancestor = document.getElementById('id'),
descendents = ancestor.getElementsByTagName('*');
// gets all descendent of ancestor
Теперь вам нужно только перебрать 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);
}
}
В зависимости от того, что вы делаете, потому что вы используете getElementsByTagName
для получения descendents
, descendents
является live NodeList, поэтому длина будет изменяться по мере добавления дополнительных узлов до ancestor
. Если вам нужно избегать этого, преобразуйте его в массив до цикла
decendents = Array.prototype.slice.call(decendents);
См. этот метод для функции многократного использования.
Ответ 2
Вы могли бы просто использовать что-то столь же простое, как это?
// 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;
}
Ответ 3
Я прокомментировал в @Paul S. ответ, что вы также можете клонировать node и использовать фрагмент документа для добавления новых вложений. Вот пример:
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);
}
Здесь вы можете увидеть демо .
Клонирование node предотвращает живое изменение DOM, поскольку атрибут стиля может иметь свойства, которые заставляют браузер перекрашивать много раз.
Ответ 4
Вы можете использовать функцию querySelectorAll forEach.
document.querySelectorAll('li').forEach(function(element) {
console.log(element);
});