javascript先序遍历DOM树的方法


Posted in Javascript onFebruary 27, 2016

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 相关文章推荐
JavaScript基本概念初级讲解论坛贴的学习记录
Feb 22 Javascript
jQuery实现ichat在线客服插件
Dec 29 Javascript
jQuery中next()方法用法实例
Jan 07 Javascript
js实现透明度渐变效果的方法
Apr 10 Javascript
JavaSacript中charCodeAt()方法的使用详解
Jun 05 Javascript
详解Node.js模块间共享数据库连接的方法
May 24 Javascript
jquery弹出框插件jquery.ui.dialog用法分析
Aug 20 Javascript
Angular 项目实现国际化的方法
Jan 08 Javascript
详解Angular5 路由传参的3种方法
Apr 28 Javascript
原生JS实现动态加载js文件并在加载成功后执行回调函数的方法
Dec 30 Javascript
vue实现双向绑定和依赖收集遇到的坑
Nov 29 Javascript
vue拖拽组件 vuedraggable API options实现盒子之间相互拖拽排序
Jul 08 Javascript
JavaScript开发者必备的10个Sublime Text插件
Feb 27 #Javascript
Javascript生成全局唯一标识符(GUID,UUID)的方法
Feb 27 #Javascript
JS原型、原型链深入理解
Feb 27 #Javascript
Javascript中Date类型和Math类型详解
Feb 27 #Javascript
原生javascript实现匀速运动动画效果
Feb 26 #Javascript
探索angularjs+requirejs全面实现按需加载的套路
Feb 26 #Javascript
JavaScript代码生成PDF文件的方法
Feb 26 #Javascript
You might like
PHP中将数组转成XML格式的实现代码
2011/08/08 PHP
PHP缓存技术的多种方法小结
2012/08/14 PHP
Symfony2获取web目录绝对路径、相对路径、网址的方法
2016/11/14 PHP
jQuery Div中加载其他页面的实现代码
2009/02/27 Javascript
ExtJS 2.0实用简明教程 之ExtJS版的Hello
2009/04/29 Javascript
JavaScript继承方式实例
2010/10/29 Javascript
JS实现随机数生成算法示例代码
2013/08/08 Javascript
JavaScript设计模式之单件模式介绍
2014/12/28 Javascript
thinkphp 表名 大小写 窍门
2015/02/01 Javascript
H5手机端多文件上传预览插件
2017/04/21 Javascript
vue.js vue-router如何实现无效路由(404)的友好提示
2017/12/20 Javascript
浅谈SpringMVC中post checkbox 多选框value的值(隐藏域方式)
2018/01/08 Javascript
默认浏览器设置及vue自动打开页面的方法
2018/09/21 Javascript
Webpack4 使用Babel处理ES6语法的方法示例
2019/03/07 Javascript
js实现中文实时时钟
2020/01/15 Javascript
vue iview 隐藏Table组件里的某一列操作
2020/11/13 Javascript
python实现socket端口重定向示例
2014/02/10 Python
python分析nignx访问日志脚本分享
2015/02/26 Python
Python使用minidom读写xml的方法
2015/06/03 Python
Python列表list解析操作示例【整数操作、字符操作、矩阵操作】
2017/07/25 Python
python监控linux内存并写入mongodb(推荐)
2017/09/11 Python
python图像常规操作
2017/11/11 Python
python的socket编程入门
2018/01/29 Python
PySide和PyQt加载ui文件的两种方法
2019/02/27 Python
Keras load_model 导入错误的解决方式
2020/06/09 Python
Python logging模块handlers用法详解
2020/08/14 Python
python Cartopy的基础使用详解
2020/11/01 Python
18-35岁旅游团的全球领导者:Contiki
2017/02/08 全球购物
英国的潮牌鞋履服饰商店:size?
2019/03/26 全球购物
牧马人澳大利亚官网:Wrangler澳大利亚
2019/10/08 全球购物
2014年节能减排工作总结
2014/12/06 职场文书
2014年减负工作总结
2014/12/10 职场文书
公司保洁员岗位职责
2015/02/13 职场文书
公司车队管理制度
2015/08/04 职场文书
一篇文章带你学习Mybatis-Plus(新手入门)
2021/08/02 Java/Android
阿里云服务器部署mongodb的详细过程
2021/09/04 MongoDB