JavaScript DOM2 - 遍历
遍历
“DOM2级遍历和范围”模块定义了两个用于辅助完成顺序遍历DOM结构的类型: NodeIterator和TreeWalker。这两个类型能够基于给定的起点对DOM结构执行深度优先( depth-first )的遍历操作。
DOM遍历是深度优先的DOM结构遍历,也就是说,移动的方向至少有两个(取决于使用的遍历类型)。遍历以给定节点为根,不可能向上超出DOM树的根节点。
任何节点都可以作为遍历的根节点。如果假设
元素为根节点,那么遍历的第一步 就是访问<p>元素,然后再访问同为<body>元素后代的两个文本节点。不过,这次遍历永远不会到达<html><head>元素,也不会到达不属于<body>元素子树的任何节点。而以document为根节点的遍历则可以访问文档中的全部节点。下图展示了对以document为根节点的DOM树进行深度优先遍历的先后顺序。NodeIterator 和TreeWalker都以这种方式遍历。
1、NodeIterator
使用document.createNodeIterator() 方法来创建它的实例。这个方法接收下列4个参数:
- root:想要作为搜索起点的数中的节点。
- whatToShow:表示想要访问哪些节点的数字代码。
- filter:是一个NodeFilter对象,或者一个表示应该接受还是某种特定节点的函数。(类似节点过滤器的函数)
- entityReferenceExpansion:布尔值表示是否扩展实体引用。这个参数在HTML页面中没有用,因为其中的实体引用不能扩展。
whatToShow参数是一个位掩码, 通过应用- -或多 个过滤器( filter )来确定要访问哪些节点。这个参数的值以常量形式在NodeFilter类型中定义,如下所示。
- NodeFilter . SHOW_ ALL:显示所有类型的节点。
- NodeFilter . SHOW_ ELEMENT:显示元素节点。
- NodeFilter . SHOW_ ATTRIBUTE:显示特性节点。由于DOM结构原因,实际上不能使用这个值。
- NodeFilter . SHOW_ TEXT:显示文本节点。
- NodeFilter . SHOW_ CDATA_ SECTION: 显示CDATA节点。对HTML页面没有用。
- NodeFilter . SHOw_ ENTITY_ REFERENCE:显示实体引用节点。对HTML页面没有用。
- NodeFil ter . SHOW_ ENTITYE:显示实体节点。对HTML页面没有用。
- NodeFil ter . SHOW_ PROCESSING_ INSTRUCTION:显示处理指令节点。对HTML页面没有用。
- NodeFilter . SHOW_ COMMENT:显示注释节点。
- NodeFilter . SHOW_ DOCUMENT: 显示文档节点。
- NodeFilter . SHOW_ DOCUMENT_TYPE: 显示文档类型节点。
- NodeFil ter . SHOW_ DOCUMENT_ FRAGMENT:显示文档片段节点。对HTML页面没有用。
- NodeFilter . SHOW_ NOTATION:显示符号节点。对HTML页面没有用。
除了NodeFilter.SHOW_ ALL之外,可以使用按位或操作符来组合多个选项,
1 | var whatToShow = NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT; |
可以通过createNodeIterator()方法的filter参数来指定自定义的NodeFilter对象,或者指定一个功能类似节点过滤器( node filter )的函数。
1 | var filter = function(node) { |
NodeIterator类型的两个主要方法是nextNode ()和previousNode()。顾名思义,在深度优先的DOM子树遍历中,nextNode ()方法用于向前前进一步,而previousNode ()用于向后后退一步。在刚刚创建的NodeIterator对象中,有一个内部指针指向根节点,因此第一次调用nextNode()会返回根节点。当遍历到DOM子树的最后一个节点时,nextNode() 返回null。previousNode()方法的工作机制类似。当遍历到DOM子树的最后一个节点,且previousNode()返回根节点之后,再次调用它就会返回null。
小例子:遍历指定节点中 <li>的元素,
1 | var mylist = document.getElementById("mylist"); //获取我们遍历起点的节点。 |
TrreWalker
TreeWalker是NodeIterator的一个更高级 的版本。除了包括 nextNode ()和previousNode ()在内的相同的功能之外,这个类型还提供了下列用于在不同方向上遍历DOM结构的方法。
- parentNode():遍历到当前节点的父节点;
- firstChild():遍历到当前节点的第一个子节点;
- lastChild():遍历到当前节点的最后一个子节点;
- nextSibling():遍历到当前节点的下一个同辈节点;
- previoussibling():遍历到当前节点的上一个同辈节点。
创建Treewalker对象要使用document. createTreewalker()方法,这个方法接受的4个参数与document . createNodeIterator ()方法相同:作为遍历起点的根节点、要显示的节点类型、过滤器和一个表示是否扩展实体引用的布尔值。由于这两个创建方法很相似,所以很容易用Treewalker 来代替NodeIterator,如下面的例子所示。
1 | var mylist = document.getElementById("mylist"); |
在这里,filter可以返回的值有所不同。除了NodeFilter .FILTER_ACCEPT 和NodeFilter.FILTER_ SKIP之外,还可以使用NodeFilter . FILTER_REJECT。 在使用NodeIterator对象时,NodeFilter . FILTER_ SKIP与NodeFilter . FILTER_ REJECT 的作用相同:跳过指定的节点。但在使用TreeWalker对象时,NodeFilter . FILTER SKIP会跳过相应节点继续前进到子树中的下一个节点,而NodeFilter . FILTER REJECT 则会跳过相应节点及该节点的整个子树。例如,将前面例子中的NodeFilter . FILTER_ SKIP 修改成NodeFilter. FILTER_ REJECT, 结果就是不会访问任何节点。这是因为第一个返回的节点是<div>,它的标签名不是”li”,于是就会返回NodeFilter . FILTER REJECT ,这意味着遍历会跳过整个子树。在这个例子中,<div>元素是遍历的根节点,于是结果就会停止遍历。
当然,Treewalker真正强大的地方在于能够在DOM结构中沿任何方向移动。使用Treewalker遍历DOM树,即使不定义过滤器,也可以取得所有<li>元素,如下面的代码所示。(前提我们知道它的结构树)
1 | var mylist = document.getElementById("mylist"); |
它的HTML结构
1 | <div id="mylist"> |
TreeWalker类型 还有一个属性,名叫 currentNode ,表示任何遍历方法在上一次遍历中返回的节点。通过设置这个属性也可以修改遍历继续进行起点,如下:
1 | var node = walker.nextNode; |
下面的例子会返回body中所有的 li 节点
1 | var mylist = document.getElementById("mylist"); |
愿你的坚持终有收获。
Use this card to join the candyhome and participate in a pleasant discussion together .
Welcome to aqing's candyhome,wish you a nice day .