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 流畅动画实现原理
Sep 08 Javascript
jQuery帮助之CSS尺寸(五)outerHeight、outerWidth
Nov 14 Javascript
javascript中&quot;/&quot;运算符常见错误
Oct 13 Javascript
js操作table示例(个人心得)
Nov 29 Javascript
浅析Node.js查找字符串功能
Sep 03 Javascript
JavaScript中的this机制
Jan 30 Javascript
JS实现点击事件统计的简单实例
Jul 10 Javascript
微信小程序实现文字跑马灯效果
May 26 Javascript
React组件中的this的具体使用
Feb 28 Javascript
MockJs结合json-server模拟后台数据
Aug 26 Javascript
vue点击按钮动态创建与删除组件功能
Dec 29 Javascript
Vue实现input宽度随文字长度自适应操作
Jul 29 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
简单实现限定phpmyadmin访问ip的方法
2013/03/05 PHP
判断php数组是否为索引数组的实现方法
2013/06/13 PHP
php编译安装php-amq扩展简明教程
2016/06/25 PHP
Ajax实现对静态页面的文章访问统计功能示例
2016/10/10 PHP
Yii2下session跨域名共存的解决方案
2017/02/04 PHP
PHP批斗大会之缺失的异常详解
2019/07/09 PHP
Laravel Eloquent ORM 实现查询表中指定的字段
2019/10/17 PHP
jQuery ui插件的使用方法代码实例
2013/05/08 Javascript
用jQuery实现一些导航条切换,显示隐藏的实例代码
2013/06/08 Javascript
JS实现兼容各浏览器解析XML文档数据的方法
2015/06/01 Javascript
JS实现可点击展开与关闭的左侧广告代码
2015/09/02 Javascript
js实现正则匹配中文标点符号的方法
2015/12/23 Javascript
基于JavaScript实现动态添加删除表格的行
2016/02/01 Javascript
leaflet的开发入门教程
2016/11/17 Javascript
Angular2 路由问题修复详解
2017/03/01 Javascript
Jquery中attr与prop的区别详解
2017/05/27 jQuery
input file样式修改以及图片预览删除功能详细概括(推荐)
2017/08/17 Javascript
详解如何用typescript开发koa2的二三事
2018/11/13 Javascript
Vue表单控件绑定图文详解
2019/02/11 Javascript
JS XMLHttpRequest原理与使用方法深入详解
2020/04/30 Javascript
js编写简易的计算器
2020/07/29 Javascript
JavaScript检测是否开启了控制台(F12调试工具)
2020/10/02 Javascript
JS addEventListener()和attachEvent()方法实现注册事件
2021/01/11 Javascript
[56:18]DOTA2上海特级锦标赛主赛事日 - 4 败者组第四轮#2 MVP.Phx VS Fnatic第二局
2016/03/05 DOTA
[41:54]2018DOTA2亚洲邀请赛 4.1 小组赛A组加赛 TNC vs Liquid
2018/04/03 DOTA
python中循环语句while用法实例
2015/05/16 Python
如何在Python函数执行前后增加额外的行为
2016/10/20 Python
Python实现的建造者模式示例
2018/08/06 Python
Python里字典的基本用法(包括嵌套字典)
2019/02/27 Python
Python中flatten( ),matrix.A用法说明
2020/07/05 Python
全球第二大家装零售商:Lowe’s
2018/01/13 全球购物
在c#中using和new这两个关键字有什么意义
2013/05/19 面试题
房屋转让协议书
2014/04/11 职场文书
医院科室评语
2015/01/04 职场文书
大学四年个人总结
2015/03/03 职场文书
Python实现日志实时监测的示例详解
2022/04/06 Python