Как сделать этот цикл рекурсивным для всех детей? - PullRequest
24 голосов
/ 26 апреля 2010

У меня есть следующее:

for (var i = 0; i < children.length; i++){
   if(hasClass(children[i], "lbExclude")){
       children[i].parentNode.removeChild(children[i]);
   }
};

Я бы хотел, чтобы он прошел через всех детей и т. Д. (Не только на верхнем уровне). Я нашел эту строку, которая, кажется, делает это:

for(var m = n.firstChild; m != null; m = m.nextSibling) {

Но мне неясно, как я отношусь к текущему ребенку, если я сделаю это переключение? У меня больше не было бы возможности уточнить индекс позиции ребенка. Есть предложения?

Спасибо!

Обновление:

Я сейчас использую следующее в соответствии с предложениями ответа. Это правильный / самый эффективный способ сделать это?

function removeTest(child) {
  if (hasClass(child, "lbExclude")) {
    child.parentNode.removeChild(child);
  }
}

function allDescendants(node) {
  for (var i = 0; i < node.childNodes.length; i++) {
    var child = node.childNodes[i];
    allDescendants(child);
    removeTest(child);
  }
}

var children = temp.childNodes;
for (var i = 0; i < children.length; i++) {
  allDescendants(children[i]);
};

Ответы [ 8 ]

41 голосов
/ 26 апреля 2010
function allDescendants (node) {
    for (var i = 0; i < node.childNodes.length; i++) {
      var child = node.childNodes[i];
      allDescendants(child);
      doSomethingToNode(child);
    }
}

Вы перебираете все дочерние элементы, и для каждого элемента вы вызываете одну и ту же функцию, и она зацикливается над дочерними элементами этого элемента.

28 голосов
/ 26 апреля 2010

Обычно у вас есть функция, которую можно вызывать рекурсивно на всех узлах. Это действительно зависит от того, что вы хотите сделать с детьми. Если вы просто хотите собрать всех потомков, то element.getElementsByTagName может быть лучшим вариантом.

var all = node.getElementsByTagName('*');

for (var i = -1, l = all.length; ++i < l;) {
    removeTest(all[i]);
}
3 голосов
/ 26 апреля 2010

Нет необходимости вызывать метод 'allDescendants' для всех дочерних элементов, потому что сам метод уже делает это. Поэтому удалите последний кодовый блок, и я думаю, что это правильное решение (а не =))

            function removeTest(child){     
                if(hasClass(child, "lbExclude")){
                    child.parentNode.removeChild(child);
                }
            }

            function allDescendants (node) {
                for (var i = 0; i < node.childNodes.length; i++) {
                  var child = node.childNodes[i];
                  allDescendants(child);
                  removeTest(child);
                }
            }           

            var children = allDescendants(temp);
1 голос
/ 15 декабря 2018

если элементы создаются в цикле, вы должны оставить индекс через id = "" data-name или что-то еще. Затем вы можете индексировать их напрямую, что будет быстрее для большинства функций, таких как (! -F). Хорошо работает для 1024 бит х 100 элементов в зависимости от того, что вы делаете.

if ( document.getElementById( cid ) ) {
 return;
} else {
  what you actually want
}

это будет быстрее в большинстве случаев, когда элементы уже загружены. только почистите страницу о перезагрузке или безопасных передачах доменов / логинах / cors и т. д., и вы делаете что-то дважды.

1 голос
/ 02 февраля 2017

Вы можете использовать BFS, чтобы найти все элементы.

function(element) {
    // [].slice.call() - HTMLCollection to Array
    var children = [].slice.call(element.children), found = 0;
    while (children.length > found) {
        children = children.concat([].slice.call(children[found].children));
        found++;
    }
    return children;
};

Эта функция возвращает всех дочерних дочерних элементов элемента.

1 голос
/ 08 июня 2015

Если у вас есть jquery и вы хотите получить все элементы-потомки, вы можете использовать:

 var all_children= $(parent_element).find('*');

Просто помните, что all_children - это коллекция HTML, а не массив. Они ведут себя аналогично, когда вы просто зацикливаетесь, но в коллекции нет многих полезных Array.prototype методов, которые могли бы вам понравиться.

0 голосов
/ 31 мая 2018

Самый простой способ сделать это в современных браузерах или с помощью babel - это. Допустим, у вас есть HTML-узел $node, чьи дети вы хотите сохранить.

Array.prototype.forEach.call($node.querySelectorAll("*"), function(node) {
  doSomethingWith(node);
});

querySelectorAll('*') на любом узле DOM даст вам все дочерние узлы элемента в NodeList. NodeList - это массивоподобный объект, поэтому вы можете использовать Array.prototype.forEach.call для перебора этого списка, обрабатывая каждого потомка один за другим в обратном вызове.

0 голосов
/ 26 апреля 2010

Если вы используете библиотеку js, это так просто:

$('.lbExclude').remove();

В противном случае, если вы хотите получить все элементы в узле, вы можете собрать их все изначально:

var nodes = node.getElementsByTagName('*');
for (var i = 0; i < nodes.length; i++) {
  var n = nodes[i];
  if (hasClass(n, 'lbExclude')) {
    node.parentNode.removeChild(node);
  }
}
...