DOM Tree Walker作为练习[JS]

时间:2016-09-03 17:04:12

标签: javascript dom

编写一个名为nextNode的函数,该函数可用于遍历DOM树的所有节点。该函数应将节点作为参数,并返回树中的下一个节点。例如,以下循环将访问每个节点一次,并且只访问一次:

 var node = document.body;
  do {
    node = nextNode(node);
  } while (node != null)

我认为从DOM来看,它应该只使用firstChild, lastChild, previousSibling, nextSibling,parentNode

下面的代码应该是我想象它的工作方式。问题在于childNodes,似乎需要for / while循环才能工作。但循环需要以某种方式记住最后一个childNodes位置并添加i + 1,因为它在do / while循环中调用。我不知道给那里什么条件,我得到无限循环。

nextNode = function(node) {
  // for/while loop?
  if (node.childNodes) {
  }
  else if (node.nextSibling) {
    node = node.nextSibling;
  }
  else {
    node = node.parentNode.nextSibling;
  }
  return node;
};

除非我完全错了。有人可以详细说明或指出我正确的方向吗?

2 个答案:

答案 0 :(得分:2)

您可以使用此功能:

var nextNode = function(node, deeperDone) {
  return !node ? undefined
       : node.childNodes.length && !deeperDone ? node.childNodes[0]
       : node.nextSibling ? node.nextSibling
       : nextNode(node.parentNode, 1);
};

它使用递归来通过父级进行回溯,因为下一个节点可能是层次结构中的几个级别。

这是一个演示:



var nextNode = function(node, deeperDone) {
  return !node ? undefined
       : node.childNodes.length && !deeperDone ? node.childNodes[0]
       : node.nextSibling ? node.nextSibling
       : nextNode(node.parentNode, 1);
};

for (var node = document.getElementById('a'); node; node = nextNode(node)) {
    if (node.id) console.log(node.id); // skip text nodes
}

<div id="a">
   <div id="b"></div>
   <div id="c">
       <div id="d"></div>
   </div>
   <div id="e">
       <div id="f">
            <div id="g"></div>
            <div id="h"></div>
            <div id="i"></div>
       </div>
       <div id="j">
            <div id="k"></div>
            <div id="l"></div>
       </div>
   </div>
   <div id="m"></div>
</div>
&#13;
&#13;
&#13;

虽然你要求一个以节点为参数的函数,但是有一个TreeWalker对象(Orial引用),这是一种游标,你可以在其上调用nextNode方法反复以步行顺序通过节点。请注意,在开始时,在移动到下一个节点之前,您也希望对root节点执行某些操作,您可以(在开始时)使用currentNode属性进行访问:

&#13;
&#13;
var walker = document.createTreeWalker(document.getElementById('a'), 
                                       NodeFilter.SHOW_ELEMENT);
do {
    console.log(walker.currentNode.id); 
} while (walker.nextNode());
&#13;
<div id="a">
   <div id="b"></div>
   <div id="c">
       <div id="d"></div>
   </div>
   <div id="e">
       <div id="f">
            <div id="g"></div>
            <div id="h"></div>
            <div id="i"></div>
       </div>
       <div id="j">
            <div id="k"></div>
            <div id="l"></div>
       </div>
   </div>
   <div id="m"></div>
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

使用createTreeWalker编写树步行者是微不足道的:

function iterateAll() {
  return document.createTreeWalker(document);
}
var nodes = iterateAll(), node;
while(node = nodes.nextNode()) {
  console.log(node + '');
}