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实现的仿Flash广告图片轮换效果
Apr 24 Javascript
javascript跑马灯悬停放大效果实现代码
Dec 12 Javascript
js中onload与onunload的使用示例
Aug 25 Javascript
JQuery做的一个简单的点灯游戏分享
Jul 16 Javascript
javascript动画算法实例分析
Jul 31 Javascript
js漂浮广告实现代码
Aug 15 Javascript
详解JavaScript中双等号引起的隐性类型转换
May 30 Javascript
jQuery实现表格与ckeckbox的全选与单选功能
Nov 24 Javascript
用node-webkit把web应用打包成桌面应用(windows环境)
Feb 01 Javascript
微信小程序授权登录及解密unionId出错的方法
Sep 26 Javascript
js实现每日签到功能
Nov 29 Javascript
通过实例了解Render Props回调地狱解决方案
Nov 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
asp和php下textarea提交大量数据发生丢失的解决方法
2008/01/20 PHP
浅谈php正则表达式中的非贪婪模式匹配的使用
2014/11/25 PHP
[原创]PHP实现SQL语句格式化功能的方法
2017/07/28 PHP
jquery checkbox,radio是否选中的判断代码
2010/03/20 Javascript
理解JavaScript中的对象 推荐
2011/01/09 Javascript
js根据给定的日期计算当月有多少天实现思路及代码
2013/02/25 Javascript
JS辨别访问浏览器判断是android还是ios系统
2014/08/19 Javascript
JavaScript的arguments对象应用示例
2014/09/15 Javascript
Angular.JS实现无限级的联动菜单(使用demo)
2017/02/08 Javascript
JS+canvas实现的五子棋游戏【人机大战版】
2017/07/19 Javascript
使用jQuery 操作table 完成单元格合并的实例
2017/12/27 jQuery
VUE 使用中踩过的坑
2018/02/08 Javascript
Vue 自定义动态组件实例详解
2018/03/28 Javascript
Vue2实时监听表单变化的示例讲解
2018/08/30 Javascript
基于Web Audio API实现音频可视化效果
2020/06/12 Javascript
JavaScript实现串行请求的示例代码
2020/09/14 Javascript
Python中利用sqrt()方法进行平方根计算的教程
2015/05/15 Python
Python数据类型详解(二)列表
2016/05/08 Python
python urllib爬取百度云连接的实例代码
2017/06/19 Python
Python cookbook(字符串与文本)在字符串的开头或结尾处进行文本匹配操作
2018/04/20 Python
python使用__slots__让你的代码更加节省内存
2018/09/05 Python
python中pika模块问题的深入探究
2018/10/13 Python
Python实现连接MySql数据库及增删改查操作详解
2019/04/16 Python
Python 共享变量加锁、释放详解
2019/08/28 Python
浅谈PyTorch中in-place operation的含义
2020/06/27 Python
浅谈pytorch中torch.max和F.softmax函数的维度解释
2020/06/28 Python
opencv 图像轮廓的实现示例
2020/07/08 Python
Zadig&Voltaire官网:法国时装品牌
2018/01/05 全球购物
英国银首饰公司:e&e Jewellery
2021/02/11 全球购物
SQL Server面试题
2013/04/04 面试题
网络教育毕业生自我鉴定
2013/10/10 职场文书
个人实用简单的自我评价
2013/10/19 职场文书
中秋节超市促销方案
2014/01/30 职场文书
药品营销专业毕业生自荐信
2014/07/02 职场文书
忠犬八公的故事观后感
2015/06/05 职场文书
2015最新婚礼司仪主持词
2015/06/30 职场文书