DOM树由文档中的所有节点(元素节点、文本节点、注释节点等)所构成的一个树结构,DOM树的解析和构建是浏览器要实现的关键功能。既然DOM树是一个树结构,那么我们就可以使用遍历树结构的相关方法来对DOM树进行遍历,同时DOM2中的"Traversal"模块又提供了两种新的类型,从而可以很方便地实现DOM树的先序遍历。

注:本文中的5种方法都是对DOM的先序遍历方法(深度优先遍历),并且只关注Element类型。

1. 使用DOM1中的基础接口,递归遍历DOM树

DOM1中为基础类型Node提供了一些api,通过这些api可以完成一些基础的DOM操作。使用递归遍历DOM树的代码比较简单,核心思想就是先处理当前节点,然后再从左到右递归遍历子节点,代码如下:

  1.   /**
  2. * 使用递归的方式先序遍历DOM树
  3. * @param node 根节点
  4. */
  5. function traversal(node){
  6. //对node的处理
  7. if(node && node.nodeType === 1){
  8. console.log(node.tagName);
  9. }
  10. var i = 0, childNodes = node.childNodes,item;
  11. for(; i < childNodes.length ; i++){
  12. item = childNodes[i];
  13. if(item.nodeType === 1){
  14. //递归先序遍历子节点
  15. traversal(item);
  16. }
  17. }
  18. }

2. 使用DOM1的基础接口,迭代遍历DOM树

与第1种方法不同,这一次使用迭代的方法遍历DOM树。使用迭代遍历DOM树相对复杂一些,关键点在于使用一个栈来维护节点的访问路径,当处理完当前节点时,先把该节点的第一个Element子节点作为下一次循环的根节点,并且按照从右到左的顺序,将当前节点的其他子元素节点压入栈中。如果当前节点没有一个Element子节点,则从栈中弹出一个Element节点作为下一次循环的根节点,直到取不到根节点为止。代码如下:

  1. /**
  2. * 使用迭代的方式先序遍历DOM树
  3. * @param node 根节点
  4. */
  5. function traversalIteration(node){
  6. var array = [], i = 0,k = 0,elementCount = 0, len = 0, childNodes,item;
  7. while(node != null){
  8. console.log(node.tagName);
  9. childNodes = node.childNodes;
  10. len = node.childNodes.length;
  11. elementCount = 0;
  12. if(len > 0){
  13. for(i = 0; i < len; i++){
  14. item = childNodes[i];
  15. if(item.nodeType === 1){
  16. elementCount++;
  17. node = item;
  18. break;
  19. }
  20. }
  21. for(k = len -1 ; k > i; k--){
  22. item = childNodes[k];
  23. if(item.nodeType == 1){
  24. elementCount++;
  25. array.push(item);
  26. }
  27. }
  28. if(elementCount < 1){
  29. node = array.pop();
  30. }
  31. }else{
  32. node = array.pop();
  33. }
  34. }
  35. }

3. 使用DOM扩展的Element Traversal API,递归遍历DOM树

DOMElement Traversal API提供了几个方便DOM遍历的接口,从而可以更加方便地取得一个节点的Element子节点。在《DOM扩展:DOM API的进一步增强[总结篇-上]》的第2节介绍了DOM扩展的Element Traversal API。代码如下:

  1. /**
  2. * 使用DOM扩展的Traversal API提供的新的接口先序遍历DOM树
  3. * @param node 根节点
  4. */
  5. function traversalUsingTraversalAPI(node){
  6. if(node && node.nodeType === 1){
  7. console.log(node.tagName);
  8. }
  9. var i = 0,len = node.childElementCount, child = node.firstElementChild;
  10. for(; i < len ; i++){
  11. traversalUsingTraversalAPI(child);
  12. child = child.nextElementSibling;
  13. }
  14. }

4. 使用NodeIterator

DOM2的"Traversal"模块提供了NodeIterator类型,使用它可以很方便地实现DOM树的先序遍历,《JavaScript高级程序设计第三版》的12.3.1节介绍了这个类型,我们这里直接给出代码如下:

  1. /**
  2. * 使用DOM2的"Traversal"模块提供的NodeIterator先序遍历DOM树
  3. * @param node 根节点
  4. */
  5. function traversalUsingNodeIterator(node){
  6. var iterator = document.createNodeIterator(node, NodeFilter.SHOW_ELEMENT,null,false);
  7. var node = iterator.nextNode();
  8. while(node != null){
  9. console.log(node.tagName);
  10. node = iterator.nextNode();
  11. }
  12. }

5. 使用TreeWalker

TreeWalker类型可以说是NodeIterator类型的增强版,《JavaScript高级程序设计第三版》的12.3.2节介绍了这个类型,我们这里也直接给出代码如下:

  1. /**
  2. * 使用DOM2的"Traversal"模块提供的TreeWalker先序遍历DOM树
  3. * @param node 根节点
  4. */
  5. function traversalUsingTreeWalker(node){
  6. var treeWalker = document.createTreeWalker(node, NodeFilter.SHOW_ELEMENT,null,false);
  7. if(node && node.nodeType === 1){
  8. console.log(node.tagName);
  9. }
  10. var node = treeWalker.nextNode();
  11. while(node != null){
  12. console.log(node.tagName);
  13. node = treeWalker.nextNode();
  14. }
  15. }

欢迎小伙伴评论交流~~

先序遍历DOM树的5种方法的更多相关文章

  1. JavaScript 算法应用: 遍历DOM树的两种方式

    1 常见的DOM树结构: 2  DOM数遍历有两种方式: 3 广度优先代码: 4 深度优先遍历代码

  2. 函数遍历DOM树

    //获取页面中的根节点--根标签   var root=document.documentElement;//html   //函数遍历DOM树   //根据根节点,调用fn的函数,显示的是根节点的名 ...

  3. jQuery向上遍历DOM树之parents(),parent(),closest()之间的区别

    http://www.poluoluo.com/jzxy/201312/253059.html 在这个sprint中,因为要写前端UI,所以用到了jQuery,但是jQuery在向上遍历DOM树的AP ...

  4. 拷贝和遍历DOM树

    一.浅拷贝: 拷贝就是复制,就相当于把一个对象中的所有内容,复制一份给另一个对象,直接复制, 或者说,就是把一个对象的地址给了另外一个对象,他们的指向相同,两个对象之间有相同的属性或者方法,都可以使用 ...

  5. JS高级---遍历DOM树

    遍历DOM树  第一个函数: 给我根节点, 我会找到所有的子节点: forDOM(根节点)  获取这个根节点的子节点  var children=根节点的.children  调用第二个函数  第二个 ...

  6. Jquery遍历筛选数组的几种方法和遍历解析json对象|Map()方法详解

    Jquery遍历筛选数组的几种方法和遍历解析json对象|Map()方法详解 一.Jquery遍历筛选数组 1.jquery grep()筛选遍历数组 $().ready( function(){ v ...

  7. JQuery遍历json数组的3种方法

    这篇文章主要介绍了JQuery遍历json数组的3种方法,本文分别给出了使用each.for遍历json的方法,其中for又分成两种形式,需要的朋友可以参考下 一.使用each遍历 $(functio ...

  8. Java遍历List集合的三种方法

    Java遍历List集合的三种方法 List<String> list = new ArrayList<String>(); list.add("aaa") ...

  9. (转载)Java中如何遍历Map对象的4种方法

    在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都 ...

随机推荐

  1. 11.20 正则表达式 断言(?=exp)

    今天看源代码,研究了一下qz写的这个方法: // 添加逗号分隔,返回为字符串 comma: function(length) { ) length = ; var source = ('' + thi ...

  2. labellmg的使用

    ---恢复内容开始--- 在powershell环境下进入到labelImg解压后的文件,我这里是D:\labelImg-master\labelImg-master 执行命令: pyrcc5 -o ...

  3. Autel MaxiTPMS TS601 Wireless TPMS Sensor Reset Relearn Activate Programming Tool

    Why Choose Autel TPMS TS601? MaxiTPMS TS601 is a TPMS tool with highest performance in the world. It ...

  4. 洛谷P1576||最小花费||dijkstra||双向建边!!

    题目描述 在n个人中,某些人的银行账号之间可以互相转账.这些人之间转账的手续费各不相同.给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元. 数据范 ...

  5. Non-decreasing Array LT665

    Given an array with n integers, your task is to check if it could become non-decreasing by modifying ...

  6. ----Arrow functions----

    Arrow functions Arrow functions表达式相比函数表达式有更短的语法,没有自己的this.argument.super或者new.target. 1.语法规则: 基础语法: ...

  7. zookeeper名字服务

    10.12.67.31 #!/bin/shmkdir -p /data/zk-install/cd /data/zk-install/wget -q -O ons_agent-1.0.5.tar.gz ...

  8. java36

    1.Main public static void main(String [ ] args) public:被jvm调用的方法,权限要足够大 static:被jvm调用的方法,不需要创建对象,直接用 ...

  9. tensorflow学习之(十一)将python代码写入文件

    #save to file import tensorflow as tf import numpy as np ##(1)Save to file 把相关变量存储到文件中 #remember to ...

  10. 如何方便的在windows测试python程序

    听说python的网页抓取模块很强大,我想试试看看能给我的网络优化工作带来什么大的帮助,于是跟随廖雪峰老师开始学习python(地址查看),因为我用的是window系统,这就给程序的测试带来了很多麻烦 ...