“DOM2级遍历和范围”模块定义了两个用于辅助完成顺序遍历DOM结构的类型:NodeIterator和TreeWalker;这两个类型能够基于给定的起点对DOM结构执行深度优先的遍历操作。
NodeIterator
类型
使用document.createNodeIterator()
方法创建新的实例。这个方法接收四个参数:
root:想要作为搜索起点的树中的节点;
whatToShow:表示要访问哪些节点的数字代码;
filter:是一个NodeFilter对象,或者一个函数(表示应该接受还是拒绝某种特定节点的函数);
entityReferenceExpansion:布尔值,表示是否扩展实体引用。在HTML页面中没用;
whatToShow:
NodeFilter.SHOW_ALL:所有类型节点;
NodeFilter.SHOW_ELEMENT:元素;
NodeFilter.SHOW_ATTRIBUTE:特性;
NodeFilter.SHOW_TEXT:文本;
NodeFilter.SHOW_COMMENT;
NodeFilter.SHOW_DOCUMENT;
NodeFilter.SHOW_DOCUMENT_TYPE;
另外还有对HTML页面没用的几个:
NodeFilter.SHOW_CDATA_SECTION;
NodeFilter.SHOW_ENTITY_REFERENCE:实体引用节点;
NodeFilter.SHOW_ENTITY:实体节点;
NodeFilter.SHOW_PROCESSING_INSTRUCTION:处理指令节点;
NodeFilter.SHOW_DOCUMENT_FRAGMENT;
NodeFilter.SHOW_NOTATION:符号节点
可以用按位或操作符来组合多个选项如:
var whatToShow = NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT;
filter
可以使用createNodeIterator()
方法的filter参数来指定自定义的NodeFilter对象,每个NodeFilter对象只有一个方法,应该访问的节点返回NodeFilter.FILTER_ACCEPT
;不应该访问的节点返回NodeFilter.FILTER_SKIP
;
可以创建包含acceptNode()
方法的对象:
var filter = {
acceptNode: function(node) {
return node.nodeName.toLowerCase() == "p" ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
}
};
也可以创建一个与acceptNode()
方法类似的函数:
var filter = function(node) {
return node.nodeName.toLowerCase() == "p" ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
}
如果不指定过滤器,那么应该传入null。
举例:
搜索document中所有的元素
var iterator = document.createNodeIterator(document.body, NodeFilter.SHOW_ELEMENT, null);
var node = iterator.nextNode();
console.log(node); //HTMLBodyElement
搜索document中所有的p元素
var filter = {
acceptNode: function(node) {
return node.nodeName.toLowerCase() == "p" ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
}
};
var iterator = document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, filter);
var node = iterator.nextNode();
console.log(node); //HTMLParagraphElement
搜索document中所有的h1元素
var filter = function(node) {
return node.nodeName.toLowerCase() == "h1" ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
}
var iterator = document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, filter);
var node = iterator.nextNode();
console.log(node); //HTMLHeadingElement
nextNode()
方法与previousNode()
方法
前者用于向前前进一步;后者用于向后后退一步。当遍历到DOM子树的最后一个节点时,nextNode()返回null;当遍历到DOM子树的最后一个节点,且previousNode()返回根节点以后,再次调用它就会返回null。
举例:
以下面的html代码为例:
<div id="div1">
<p><b>Hello</b> world!</p>
<ul>
<li>List item 1</li>
<li>List item 2</li>
<li>List item 3</li>
</ul>
</div>
遍历div元素中所有的节点
var div = document.getElementById("div1");
var iterator = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT, null, false);
var node = iterator.nextNode();
while(node !== null){
console.log(node.nodeName); //输出标签名
node = iterator.nextNode();
}
// [L] repetition.html:24 DIV
// [L] repetition.html:24 P
// [L] repetition.html:24 B
// [L] repetition.html:24 UL
// [L] repetition.html:24 LI
// [L] repetition.html:24 LI
// [L] repetition.html:24 LI
遍历div中所有的li元素中的文本
var div = document.getElementById("div1");
var filter = function(node) {
if (node.nodeName.toLowerCase() == "li") {
return NodeFilter.FILTER_ACCEPT;
} else {
return NodeFilter.FILTER_SKIP;
}
};
var iterator = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT, filter, false);
var node = iterator.nextNode();
while (node !== null) {
console.log(node.firstChild.nodeValue);
node = iterator.nextNode();
}
// [L] repetition.html:31 List item 1
// [L] repetition.html:31 List item 2
// [L] repetition.html:31 List item 3
TreeWalker
类型
这个类型比上面那个更高级,除了包括nextNode()
和previousNode()
在内的相同的功能之外,这个类型还提供了下列用于在不同方向上遍历DOM结构的方法。如:
parentNode():遍历到当前节点的父节点;
firstChild():...第一个子节点;
lastChild():...最后一个子节点;
nextSibling():...当前节点的下一个同辈节点;
previousSibling():...当前节点的上一个同辈节点;
createTreeWalker()
方法
该方法用于创建TreeWalker对象,document.createTreeWalker()
方法接收4个参数,与document.createNodeIterator()
方法一致。其中的currentNode
属性,表示任何遍历方法在上一次遍历中返回的接待你。通过设置这个属性也可以修改遍历继续进行的节点。如:
var div = document.getElementById("div1");
var walker = document.createTreeWalker(div, NodeFilter.SHOW_ELEMENT, null, false);
var node = walker.currentNode; //currentNode返回当前节点 Div
console.log(node.nodeName); //DIV
walker.currentNode = document.getElementsByTagName("li")[0];
node = walker.currentNode;
console.log(node.firstChild.nodeValue); //List item 1
var secLiElem = walker.nextSibling();
console.log(secLiElem.firstChild.nodeValue); //List item 2
举例:
以下面的html代码为例:
<div id="div1">
<p><b>Hello</b> world!</p>
<ul>
<li>List item 1</li>
<li>List item 2</li>
<li>List item 3</li>
</ul>
</div>
遍历div元素中所有的节点
var div = document.getElementById("div1");
var walker = document.createTreeWalker(div, NodeFilter.SHOW_ELEMENT, null, false);
var node = walker.nextNode();
while(node !== null){
console.log(node.nodeName);
node = walker.nextNode();
}
// [L] repetition.html:24 P
// [L] repetition.html:24 B
// [L] repetition.html:24 UL
// [L] repetition.html:24 LI
// [L] repetition.html:24 LI
// [L] repetition.html:24 LI
遍历div元素中所有的li元素中文本
var div = document.getElementById("div1");
var walker = document.createTreeWalker(div, NodeFilter.SHOW_ELEMENT, null, false);
var node = walker.currentNode; //currentNode返回当前节点 Div
walker.firstChild(); //转到p
walker.nextSibling(); //转到ul
node = walker.firstChild(); //转到li
while(node !== null){
console.log(node.firstChild.nodeValue);
node = walker.nextNode();
}
// [L] repetition.html:27 List item 1
// [L] repetition.html:27 List item 2
// [L] repetition.html:27 List item 3
由于IE中没有对应的类型和方法,所以使用遍历的夸浏览器解决方案非常少见。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。