TreeWalker是NodeIterator的一个更高级的版本。

TreeWalker的创建

document.createTreeWalker(root, whatToShow, filter, EntityReferenceExpansion)

其中接收的参数与 document.createNodeIterator相同,作用也类似

举个栗子:

HTML结构:

<div id="root"> 
  <p>hello</p> 
  <div>  
    <p>world</p> 
    <ul> 
      <li> 
        <p>html</p> 
      </li> 
    </ul> 
  </div> 
</div>
var filter = function(node){ 
return node.tagName.toLowerCase() == 'p' ? 
NodeFilter.FILTER_ACCEPT: 
NodeFilter.FILTER_SKIP; 
} 
 
var walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, filter, false); 
 
var node = walker.nextNode(); 
 
while(node !== null){ 
console.log( node.tagName ); 
node = walker.nextNode(); 
}

结果输出:P P P(这里做一行展示,实际在浏览器中是分行打印的)

TreeWalker与NodeIterator中filter区别

在上一篇,使用NodeIterator对象时,NodeFilter.FILTER_SKIP和NodeFilter.FILTER_REJECT的作用是相同的:跳过指定的节点;但是,在使用TreeWalker对象时,NodeFilter.FILTER_SKIP会跳过相应的子节点继续前进到子树的下个节点,而NodeFilter.FILTER_REJECT则会跳过以及该节点的整个子树

可以把上面的demo改造一下,即把NodeFilter.FILTER_SKIP替换成NodeFilter.FILTER_REJECT:

<div id="root"> 
  <p>hello</p> 
  <div>  
    <p>world</p> 
    <ul> 
      <li> 
        <p>html</p> 
      </li> 
    </ul> 
  </div> 
</div>
var filter = function(node){ 
return node.tagName.toLowerCase() == 'p' ? 
NodeFilter.FILTER_ACCEPT: 
NodeFilter.FILTER_REJECT; 
} 
 
var walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, filter, false); 
 
var node = walker.nextNode(); 
 
while(node !== null){ 
console.log( node.tagName ); 
node = walker.nextNode(); 
}

结果输出:P。

差别很明显,当指针遍历第一个P节点后,紧接着是DIV节点,而NodeFilter.FILTER_REJECT则会跳过DIV节点以及该节点的整个子树。

TreeWalker中更好的方法应用

除了nextNode()和previousNode(),TreeWalker还提供了更好用灵活的遍历DOM结构的方法:

parentNode():遍历到当前节点的父节点;
firstChild():遍历到当前节点的第一个子节点;
lastChild():遍历到当前节点的最后一个子节点;
nextSibling():遍历到当前节点的下一个同辈节点;
previousSibling():遍历到当前节点的上一个同辈节点;

根据上面的方法,即使不使用filter过滤器也能取得指定元素li

HTML结构

<div id="root"> 
  <p>hello</p> 
  <section>  
    <p>world</p> 
    <ul> 
      <li></li> 
      <li></li> 
      <li></li> 
    </ul> 
  </section> 
</div>
var walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, null, false); 
 
walker.lastChild(); //指针跳转到section 
 
walker.lastChild(); //指针跳转到ul 
 
var node = walker.firstChild(); //指针跳转到第一个li 
 
while(node !== null){ 
console.log( node.tagName ); 
node = walker.nextSibling(); 
}

结果输出:LI LI LI

TreeWalker中的currentNode

currentNode属性表示任何遍历方法在上一次遍历中返回的节点:

var node = walker.nextNode();  
node === walker.currentNode //true


currentNode属性还可以修改遍历的起点:

walker.currentNode = document.body
————————————————
版权声明:本文为CSDN博主「TianyuCool」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_35087256/article/details/80920508


发布评论
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

DOM结构深度优先遍历(一):NodeIterator知识解答
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。