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 相关文章推荐
Jquery 基础学习笔记之文档处理
May 29 Javascript
JQuery中的事件及动画用法实例
Jan 26 Javascript
基于socket.io+express实现多房间聊天
Mar 17 Javascript
一道优雅面试题分析js中fn()和return fn()的区别
Jul 05 Javascript
极力推荐10个短小实用的JavaScript代码段
Aug 03 Javascript
Express系列之multer上传的使用
Oct 27 Javascript
jQuery 导航自动跟随滚动的实现代码
May 30 jQuery
Webpack devServer中的 proxy 实现跨域的解决
Jun 15 Javascript
超出JavaScript安全整数限制的数字计算BigInt详解
Jun 24 Javascript
Vue中使用clipboard实现复制功能
Sep 05 Javascript
js中null与空字符串&quot;&quot;的区别讲解
Jan 17 Javascript
elementui更改el-dialog关闭按钮的图标d的示例代码
Aug 04 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 dirname()与__FILE__常量的应用
2013/06/24 PHP
PHP实现的DES加密解密封装类完整实例
2017/04/29 PHP
作为PHP程序员你要知道的另外一种日志
2018/07/30 PHP
PHP常用函数之格式化时间操作示例
2019/10/21 PHP
自动生成文章摘要的代码[JavaScript 版本]
2007/03/20 Javascript
基于jQuery UI CSS Framework开发Widget的经验
2010/08/21 Javascript
javascript 弹出窗口中是否显示地址栏的实现代码
2011/04/14 Javascript
js 有框架页面跳转(target)三种情况下的应用
2013/04/09 Javascript
浅析JS刷新框架中的其他页面 &amp;&amp; JS刷新窗口方法汇总
2013/07/08 Javascript
textarea 控制输入字符字节数(示例代码)
2013/12/27 Javascript
Jquery焦点与失去焦点示例应用
2014/06/10 Javascript
基于socket.io和node.js搭建即时通信系统
2014/07/30 Javascript
jQuery老黄历完整实现方法
2015/01/16 Javascript
JS取得绝对路径的实现代码
2015/01/16 Javascript
js判断手机号运营商的方法
2015/10/23 Javascript
设置jquery UI 控件的大小方法
2016/12/12 Javascript
微信小程序跳转到其他网页(外部链接)的实现方法
2019/09/20 Javascript
react+antd 递归实现树状目录操作
2020/11/02 Javascript
[59:42]Secret vs Alliacne 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
Django中间件实现拦截器的方法
2018/06/01 Python
Flask框架学习笔记之表单基础介绍与表单提交方式
2019/08/12 Python
Python3 requests文件下载 期间显示文件信息和下载进度代码实例
2019/08/16 Python
Python-numpy实现灰度图像的分块和合并方式
2020/01/09 Python
python3用PyPDF2解析pdf文件,用正则匹配数据方式
2020/05/12 Python
is_file和file_exists效率比较
2021/03/14 PHP
Roxy美国官网:澳大利亚冲浪、滑雪健身品牌
2016/07/30 全球购物
怎么处理XML的中文问题
2015/03/26 面试题
怎样自定义一个异常类
2016/09/27 面试题
市场营销职业生涯规划书范文
2014/01/12 职场文书
投标邀请书范文
2014/01/31 职场文书
幼儿园毕业家长感言
2014/02/10 职场文书
物流毕业生个人的自我评价
2014/02/13 职场文书
工程技术员岗位职责
2014/03/02 职场文书
高中学生期末评语
2014/04/25 职场文书
幼儿园2014年度工作总结
2014/11/10 职场文书
2019年幼儿园管理条例范本!
2019/07/17 职场文书