dom树由文档中的所有节点(元素节点、文本节点、注释节点等)所构成的一个树结构,dom树的解析和构建是浏览器要实现的关键功能。既然dom树是一个树结构,那么我们就可以使用遍历树结构的相关方法来对dom树进行遍历,同时dom2中的traversal模块又提供了两种新的类型,从而可以很方便地实现dom树的先序遍历。
注:本文中的5种方法都是对dom的先序遍历方法(深度优先遍历),并且只关注element类型。
1. 使用dom1中的基础接口,递归遍历dom树
dom1中为基础类型node提供了一些api,通过这些api可以完成一些基础的dom操作。使用递归遍历dom树的代码比较简单,核心思想就是先处理当前节点,然后再从左到右递归遍历子节点,代码如下:
/**
* 使用递归的方式先序遍历dom树
* @param node 根节点
*/
function traversal(node){
//对node的处理
if(node && node.nodetype === 1){
console.log(node.tagname);
}
var i = 0, childnodes = node.childnodes,item;
for(; i < childnodes.length ; i++){
item = childnodes[i];
if(item.nodetype === 1){
//递归先序遍历子节点
traversal(item);
}
}
}
2. 使用dom1的基础接口,迭代遍历dom树
与第1种方法不同,这一次使用迭代的方法遍历dom树。使用迭代遍历dom树相对复杂一些,关键点在于使用一个栈来维护节点的访问路径,当处理完当前节点时,先把该节点的第一个element子节点作为下一次循环的根节点,并且按照从右到左的顺序,将当前节点的其他子元素节点压入栈中。如果当前节点没有一个element子节点,则从栈中弹出一个element节点作为下一次循环的根节点,直到取不到根节点为止。代码如下:
/**
* 使用迭代的方式先序遍历dom树
* @param node 根节点
*/
function traversaliteration(node){
var array = [], i = 0,k = 0,elementcount = 0, len = 0, childnodes,item;
while(node != null){
console.log(node.tagname);
childnodes = node.childnodes;
len = node.childnodes.length;
elementcount = 0;
if(len > 0){
for(i = 0; i < len; i++){
item = childnodes[i];
if(item.nodetype === 1){
elementcount++;
node = item;
break;
}
}
for(k = len -1 ; k > i; k--){
item = childnodes[k];
if(item.nodetype == 1){
elementcount++;
array.push(item);
}
}
if(elementcount < 1){
node = array.pop();
}
}else{
node = array.pop();
}
}
}
3. 使用dom扩展的element traversal api,递归遍历dom树
domelement traversal api提供了几个方便dom遍历的接口,从而可以更加方便地取得一个节点的element子节点。在《dom扩展:dom api的进一步增强[总结篇-上]》的第2节介绍了dom扩展的element traversal api。代码如下:
/**
* 使用dom扩展的traversal api提供的新的接口先序遍历dom树
* @param node 根节点
*/
function traversalusingtraversalapi(node){
if(node && node.nodetype === 1){
console.log(node.tagname);
}
var i = 0,len = node.childelementcount, child = node.firstelementchild;
for(; i < len ; i++){
traversalusingtraversalapi(child);
child = child.nextelementsibling;
}
}
4. 使用nodeiterator
dom2的"traversal"模块提供了nodeiterator类型,使用它可以很方便地实现dom树的先序遍历,《javascript高级程序设计第三版》的12.3.1节介绍了这个类型,我们这里直接给出代码如下:
/**
* 使用dom2的"traversal"模块提供的nodeiterator先序遍历dom树
* @param node 根节点
*/
function traversalusingnodeiterator(node){
var iterator = document.createnodeiterator(node, nodefilter.show_element,null,false);
var node = iterator.nextnode();
while(node != null){
console.log(node.tagname);
node = iterator.nextnode();
}
}
5. 使用treewalker
treewalker类型可以说是nodeiterator类型的增强版,《javascript高级程序设计第三版》的12.3.2节介绍了这个类型,我们这里也直接给出代码如下:
/**
* 使用dom2的"traversal"模块提供的treewalker先序遍历dom树
* @param node 根节点
*/
function traversalusingtreewalker(node){
var treewalker = document.createtreewalker(node, nodefilter.show_element,null,false);
if(node && node.nodetype === 1){
console.log(node.tagname);
}
var node = treewalker.nextnode();
while(node != null){
console.log(node.tagname);
node = treewalker.nextnode();
}
}
以上就是为大家分享的javascript先序遍历dom树的方法,希望对大家的学习有所帮助。
更多javascript先序遍历dom树的方法。
