NodeIterator和TreeWalker这2个类型可以基于给定的起点对DOM结构执行深度优先遍历。(我测试用的浏览器是Chrome,介绍说IE不支持DOM遍历,但是不知道最新的IE支持不支持)

  1、NodeIterator

    使用document.createNodeIterator()方法创建新实例,该方法接受4个参数:

      (1)、root:要访问的树的根节点。

      (2)、whatToShow:要访问的节点的数字代码。

      (3)、filter:是一个NodeFilter对象,或者一个表示过滤特定节点的函数。

      (4)、entityReferenceExpansion:布尔值,表示是否要扩展实体引用。

    whatToShow参数是一个位掩码,通过应用1或多个过滤器来确定要访问哪些节点。这个参数的值以常量的形式在NodeFilter类型中定义,具体的可以搜一下,同事可以使用"||"操作符来组合多个选项。

    Filter参数用来自定义NodeFilter对象,或者指定一个过滤特定节点的函数。每个NodeFilter对象只有一个方法,即acceptNode();如果访问了给定的节点,该方法返回NodeFilter.FILTER_ACCEPT,如果访问了未给定的节点,该方法返回NodeFilter.FILTER_SKIP。由于NodeFilter是一个抽象的类型,因此不能直接创建它的实例。只要创建一个包含acceptNode()方法的对象,然后将这个对象传入createNodeIterator()中即可。

    例如,下列代码展示了创建一个只显示<p>元素的节点迭代器:

  1. var filter = {
  2. acceptNode: function(node) {
  3. return node.tagName.toLowerCase() == 'p' ?
  4. NodeFilter.FILTER_ACCEPT :
  5. NodeFilter.FILTER_SKIP;
  6. }
  7. };
  8.  
  9. var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT, filter, false);

    第三个参数也可以是一个与acceptNode()方法类似的函数,如下:

  1. var filter = function(node) {
  2. return node.tageName.toLowerCase == 'p' ?
  3. NodeFilter.FILTER_ACCEPT :
  4. NodeFilter.FILTER_SKIP;
  5. }
  6. };
  7.  
  8. var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT, filter, false);

    如果不指定过滤器,那么第三个参数就设置为null。

    NodeIterator类型的两个主要方法是nextNode()和previousNode()。在新创建的NodeIterator对象中,有一个内部指针指向根节点,第一次调用nextNode()会返回根节点。当遍历到DOM子树的最后一个节点时,nextNode()返回null。同理,当遍历到DOM子树的最后一个节点,且previousNode()返回根节点之后,再次调用它就会返回null。

    

    假设有如下一段代码,我们要去除里面每一个<li>节点

  1.   <div id="div1">
  2.   <div></div>
  3.   <ul>
  4.   <li>0</li>
  5.   <li>1</li>
  6.   <li>2</li>
  7.   <li>3</li>
  8.   <li>4</li>
  9.   <li>5</li>
  10.   <li>6</li>
  11.   </ul>
  12.   </div>
  1.   <script>
  2. var div = document.getElementById('div1');
  3. var filter = function(node) {
  4. return node.tagName.toLowerCase() == 'li' ? NodeFilter.FILTER_ACCEPT :NodeFilter.FILTER_SKIP;
  5. };
  6.  
  7. var iterator = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT, filter, false);
  8.  
  9. var node = iterator.nextNode();
  10. var nodes = [];
  11. while (node !== null) {
  12. nodes.push(node.tagName.toLowerCase());
  13. node = iterator.nextNode();
  14. }
  15. console.log(nodes);
  16.   </script>

    

  2、TreeWalker

    TreeWalker是NodeIterator的一个更高级的版本。除了包括nextNode()和previousNode()在内的相同功能之外,该类型还提供了下列方法:

      (1)、parentNode():遍历到当前节点的父节点。

      (2)、firstChild():遍历到当前节点的第一个子节点。

      (3)、lastChild():遍历到当前节点的最后一个子节点。

      (4)、nextSibling():遍历到当前节点的下一个兄弟节点。

      (5)、previousSibling():遍历到当前节点的上一个兄弟节点。

    创建TreeWalker对象要使用document.createTreeWalker()方法,该方法接受4个参数(与document.createNodeIterator()方法相同):作为遍历起点的根节点、要显示的节点类型、过滤器和一个表示是否扩展实体引用的布尔值。

    基础的使用和document.createNodeIterator()很相似:

  1. var filter = {
  2. acceptNode: function(node) {
  3. return node.tagName.toLowerCase() == 'p' ?
  4. NodeFilter.FILTER_ACCEPT :
  5. NodeFilter.FILTER_SKIP;
  6. }
  7. };
  8.  
  9. var iterator = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, filter, false);

    filter的返回值除了NodeFilter.FITLER_ACCEPT和NodeFilter.FILTER_SKIP之外,还可以使用NodeFilter.FILTER_REJECT。在使用NodeFitler对象时,NodeFilter.FILTER_SKIP和NodeFitler.FILTER_REJECT的作用相同:跳过指定节点。但在使用TreeWalker对象时,NodeFilter.FILTER_SKIP会跳过相应节点继续前进到该节点的子树的下一个节点;而NodeFilter.FILTER_REJECT则会跳过相应节点及该节点的整个子树。

    当然,TreeWalker真正强大的地方在于能够在DOM结构中沿任何方向移动。

  1. <div id="div1">
  2. <div></div>
  3. <ul>
  4. <li>0</li>
  5. <li>1</li>
  6. <li>2</li>
  7. <li>3</li>
  8. <li>4</li>
  9. <li>5</li>
  10. <li>6</li>
  11. </ul>
  12. </div>
  13.  
  14. <script>
  15. var div = document.getElementById('div1');
  16. var walker = document.createTreeWalker(div, NodeFilter.SHOW_ELEMENT, null, false);
  17.  
  18. walker.firstChild(); //转到<div>
  19. walker.nextSibling(); //转到<ul>
  20.  
  21. var node = walker.firstChild(); //转到第一个<li>
  22. var nodes = [];
  23. while (node !== null) {
  24. nodes.push(node.tagName.toLowerCase());
  25. node = walker.nextSibling();
  26. }
  27. console.log(nodes);
  28. </script>

    

    TreeWalker类型还有一个属性,叫做currentNode,表示任何遍历方法在上一次遍历中返回的节点。通过设置这个属性也可以修改遍历继续进行的起点。

    

DOM2级提供的对DOM结构执行深度优先遍历 笔记的更多相关文章

  1. 关于DOM2级事件的事件捕获和事件冒泡

    DOM2级事件中addEventListener的执行机制,多个addEventListener同时添加时的执行先后规律: W3C的DOM事件触发分为三个阶段:①.事件捕获阶段,即由最顶层元素(一般是 ...

  2. js 中用Dom2级事件处理函数(改变样式)

    下面这些客户端 javascript代码用到了事件,它给一个很重要的事件--“load" 事件注册了一个事件处理程序.同时展示了注册”click“事件处理函数更高级的一种方法 <!do ...

  3. 关于DOM事件流、DOM0级事件与DOM2级事件

    一.DOM 事件模型 DOM 事件模型包括捕获和冒泡,捕获是从上往下到达目标元素,冒泡是从当前元素,也就是目标元素往上到 window 二.流 流的概念,在现今的 JavaScript 中随处可见.比 ...

  4. 2015-03-12——简析DOM2级事件

    DOM2级事件 事件的几种类型:对象事件,鼠标事件,键盘事件,表单事件,W3CDOM事件,以及针对浏览器的事件. 对象事件:window对象,也是javascript对象.load  适用于windo ...

  5. 测试DOM0级事件和DOM2级事件的堆叠

    1. 问题 如果大家看过北风网CJ讲师的Javascript视频教程,就可以看到其封装了一个很强的事件添加和删除函数,如下所示 function addEvent(obj, evtype, fn) { ...

  6. JavaScript 【非IE DOM2级XML】

    DOM2中的XML IE可以实现了对XML字符串或XML文件的读取,其他浏览器也各自实现了对XML处理功能.DOM2级在document.implementaion中引入了createDocument ...

  7. DOM1级问题与DOM2级事件

    前几天有小伙伴问过我一个问题,为什么有DOM 0级事件以及DOM2级事件,但是却没有DOM1级事件呢?那我们今天就来说一说DOM的级别问题. 同时推荐伙伴们可以看看尚学堂有关JavaScript BO ...

  8. DOM0级与DOM2级

    定义: 0级DOM 分为2个:一是在标签内写onclick事件  二是在JS写onlicke=function(){}函数 1) <input id="myButton" t ...

  9. js DOM0级事件和DOM2级事件

    注册事件有两种方式,分别是DOM0级和DOM2级 DOM0级就是通过事件绑定的形式dom元素只能有(绑定)一个事件处理函数,他的特点是同一个元素绑定相同事件, 后面函数会覆盖前面的 绑定: dom.o ...

随机推荐

  1. CPrimerPlus第11章第10题

    题目: 编写一个程序,读取输入,直到读入了10个字符串或遇到EOF,由二者中最先被满足的那个终止读取过程.这个程序可以为用户提供一个有5个选项的菜单:输出初始字符串列表.按ASCII顺序输出字符串.按 ...

  2. SQL中NULL值

    SQL的表达式,除了IS NULL和NOT NULL以外,只要出现NULL值结果都为FALSE 简单的例子: SELECT * FROM table WHERE name!='abc' 只要name值 ...

  3. mysql安装时到最后start service时就不响应了的解决方法

  4. STM32F412应用开发笔记之四:与远红外炭氢传感器通讯

    远红外炭氢传感器是在多组分气体传感器中用来检测甲烷和丙烷浓度的,采用单总线串行通讯,TTL电平.所以我们需要用到UART口来实现与远红外炭氢传感器的通讯. 远红外传感器就是这个样子的: 再来一张进气和 ...

  5. 手机端页面自适应解决方案-rem布局

    rem布局 布局前插入原生js即可 (function (doc, win) { var docEl = doc.documentElement, resizeEvt = 'orientationch ...

  6. 用C++实现的解数独(Sudoku)程序

    我是一个C++初学者,控制台实现了一个解数独的小程序. 代码如下: //"数独游戏"V1.0 //李国良于2016年11月11日编写完成 #include <iostream ...

  7. LeetCode 368

    题目描述: Given a set of distinct positive integers, find the largest subset such that every pair (Si, S ...

  8. javascript 转盘抽奖代码和计数器代码

    要介绍了javascript圆盘抽奖程序实现原理和完整代码例子,需要的朋友可以参考下  看到网页上有不少大转盘抽奖的应用,心血来潮也想弄个.于是找了点资料自己研究...  效果预览: 一.模拟抽奖的实 ...

  9. 优化一个奇葩表设计上的全表扫描SQL

    之前在一个比较繁忙的系统抓到的耗时长.消耗CPU多的一条SQL,如下:SELECT * FROM Z_VISU_DATA_ALARM_LOG TWHERE TO_DATE(T.T_TIMESTR, ' ...

  10. Leetcode: Palindrome Partitioning II

    参考:http://www.cppblog.com/wicbnu/archive/2013/03/18/198565.html 我太喜欢用dfs和回溯法了,但是这些暴力的方法加上剪枝之后复杂度依然是很 ...