龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > Javascript编程 >

JavaScript DOM文档遍历实战(1)(2)

时间:2013-03-06 14:58来源:未知 作者:admin 点击:
分享到:
复杂的节点遍历 在上面的学习中我们好像没有遇到过大的阻碍,下面我们以一个导航条为实例: div id = menu h1 我的导航条 / h1 ul id = nav li a href = # HOME / a

复杂的节点遍历

在上面的学习中我们好像没有遇到过大的阻碍,下面我们以一个“导航条”为实例:

  1. <div id="menu"> 
  2.     <h1>我的导航条</h1>            
  3.     <ul id="nav"> 
  4.        <li><a href="#">HOME</a></li> 
  5.        <li><a href="#">(X)Html / Css</a></li> 
  6.        <li><a href="#">Ajax / RIA</a></li> 
  7.        <li><a href="#">GoF</a></li> 
  8.        <li><a href="#">JavaScript</a></li> 
  9.        <li><a href="#">JavaWeb</a></li> 
  10.        <li><a href="#">jQuery</a></li> 
  11.        <li><a href="#">MooTools</a></li> 
  12.        <li><a href="#">Python</a></li> 
  13.        <li><a href="#">Resources</a></li> 
  14.     </ul> 
  15. </div>  

首先我想把看一下我的导航条下有多少个子节点。我第一想到的是前面我学过的查找元素的2种方法:

getElementById() # 通过ID属性查找元素

该方法将返回一个与那个有着给定id属性值的元素节点相对应的对象。

getElementsByTagName() # 通过标签名称查找元素

该方法返回一个对象数组,每个对象分别对应着文档里有着给定标签的一个元素。

  1. <script type="text/javascript"> 
  2. /*  
  3. 通过ID属性查找元素 ,用的是文档对象的getElementById()方法,  
  4. 查找到我们想要的元素对象,根据这个节点元素的 childNodes 属性,  
  5. 遍历出所有的子节点对象。  
  6. */  
  7. function queryElementsId(){  
  8.   var elemensArray,nav,nav_list;  
  9.   elemensArray=[];  
  10.   nav=document.getElementById("nav");  
  11.   /*注意IE和FF中处理Text节点上存在着一些差异*/  
  12.      navnav_list=nav.childNodes;  
  13.      for(var i=0;i<nav_list.length;i++){  
  14.     elemensArray[elemensArray.length]=nav_list[i];  
  15.     //elemensArray.push(nav_list[i]); //同上一样的结果  
  16.      }  
  17.   return elemensArray;  
  18.    
  19. }  
  20. /*  
  21. 我们观察到我的导航条是有规律的,是用无序列表元素组成的,只有定位到 &lt;ul&gt;元素  
  22. ;然后把getElementsByTagName()方法可以返回相同元素对象的集合,  
  23. 查用它找一组元素,太方便了。  
  24. */  
  25. function queryElementsTagName(){  
  26.  var elemensArray,nav,nav_list;  
  27.  elemensArray=[];  
  28.  var nav=document.getElementById("nav");  
  29.  var navnav_list=nav.getElementsByTagName("li");//返回相同的一组元素  
  30.  for(var i=0;i<nav_list.length;i++){  
  31.   elemensArray[elemensArray.length]=nav_list[i];  
  32.   //elemensArray.push(nav_list[i]); //同上一样的结果  
  33.  }  
  34.  return elemensArray;  
  35.    
  36. }  
  37. </script>  

节点遍历

那我们接下来,测一下是否是我们想要的东西:

  1. <script type="text/javascript"> 
  2. window.onload=function(){  
  3.      /*第一个方法*/  
  4.      var listqueryElementsId();   
  5.   /*第二个方法*/  
  6.  //var listqueryElementsTagName();   
  7.  var s="";  
  8.  for(var i=0;i<list.length;i++){  
  9.   s+=list[i].nodeName+"n";   
  10.     }  
  11.  alert(s);  
  12.  }  
  13. </script>  

先看一下第一个方法queryElementsId()好像我们在IE中没有发现有什么问题,那我们在Firefox中看一下是否也是我们想要的结果。

这时,问题出现了,不同的浏览器在判断何为Text节点上存在着一些差异,例如在A级浏览器中的FF和IE就有很大的差异,FireFox会把元素之间的空白、换行、tab都是Text节点,IE下会把空白全部忽略掉,只有内联元素(如em,span)后的换行、空格、tab会被认为是一个Text。既然遇到了问题那我们就得解决问题,问题的根源我们也知道了,那相应的解决方案就好做了。

方法一:

  1. <script type="text/javascript"> 
  2. /*  
  3. 《精通javascript》上提供了一个函数,用于处理xm中的这些空格,其作用原理就是找出文本节点,并删除这些节点,以达到删除这些空格的目的。  
  4. */  
  5.    
  6. function cleanWhitespace(element){  
  7.     //如果不提供参数,则处理整个HTML文档  
  8.     elementelement = element || document;  
  9.     //使用第一个子节点作为开始指针  
  10.     var cur = element.firstChild;  
  11.    
  12.     //一直到没有子节点为止  
  13.     while (cur != null){  
  14.         //如果节点为文本节点,应且包含空格  
  15.         if ( cur.nodeType == && ! /S/.test(cur.nodeValue)){  
  16.             //删除这个文本节点  
  17.             element.removeChild( cur );  
  18.    
  19.             //否则,它就是一个元素  
  20.         } else if (cur.nodeType == 1){  
  21.             //递归整个文档  
  22.             cleanWhitespace( cur );  
  23.         }  
  24.    
  25.         curcur = cur.nextSibling;//遍历子节点  
  26.     }  
  27. }  
  28. </script>  

方法二:

  1. <script type="text/javascript"> 
  2.    
  3. /*  
  4. 最后,利用数组写了一个函数,能够有效的处理dom中的空格,其原理就是将一个元素的的父元素找出来,然后通过它父元素的childNodes属性找出该元素的所有兄弟元素。遍历该元素和它的兄弟元素,将所有元素节点放在一个数组里。这样调用这个数组,就只有元素节点而没有文本节点,也就没有了讨厌的空格.  
  5.    
  6. */  
  7.    
  8. function cleanWhitespaces(elem){  
  9.     //如果不提供参数,则处理整个HTML文档  
  10.  var elemelem = elem || document;   
  11.  var parentElem = elem.parentNode; //返回一个节点的父类节点  
  12.  var childElem = parentElem.childNodes; //返回一个节点的子节点的节点列表  
  13.  var childElemArray = new Array;   
  14.  for (var i=0; i<childElem.length; i++){  
  15.   if (childElem[i].nodeType==1){//把所有节点是元素节点类型的节点存放到数组里  
  16.    childElemArray.push(childElem[i]);   
  17.   }  
  18.  }  
  19.     return childElemArray;   
  20. }   
  21. </script>  

方法三:推荐

  1. <script type="text/javascript"> 
  2. /*  
  3. 原理是对元素的所有的子节点做一个遍历。然后做一个判断,如果是子元素节点(nodeType = 1),则遍历该子元素的所有的子节点,用递归检查是否包含空白节点;如果处理的子节点是文本节点(nodeType = 3),则检查是否是纯粹的空白节点,如果是,就将它从xml对象中删除。  
  4. */  
  5. function removeWhitespace(xml){  
  6.     var loopIndex;  
  7.    
  8.     for (loopIndex = 0; loopIndex < xml.childNodes.length; loopIndex++){  
  9.         var currentNode = xml.childNodes[loopIndex];  
  10.         if (currentNode.nodeType == 1){  
  11.             removeWhitespace(currentNode);  
  12.         }  
  13.    
  14.         if (((/^s+$/.test(currentNode.nodeValue))) &&(currentNode.nodeType == 3)){  
  15.             xml.removeChild(xml.childNodes[loopIndex--]);  
  16.         }  
  17.     }  
  18. }  
  19. </script>  

好了,我们在验证一下,#Text节点问题是否处理掉了。那我们就用方法3 中removeWhitespace(nav)方法来处理queryElementsId()方法中的#Text节点问题。

  1. <script type="text/javascript"> 
  2. function queryElementsId(){  
  3.   var elemensArray,nav,nav_list;  
  4.   elemensArray=[];  
  5.   nav=document.getElementById("nav");  
  6.   /*处理#Text节点问题*/  
  7.   removeWhitespace(nav);  
  8.    
  9.   /*注意IE和FF中处理Text节点上存在着一些差异*/  
  10.      navnav_list=nav.childNodes;  
  11.      for(var i=0;i<nav_list.length;i++){  
  12.     elemensArray[elemensArray.length]=nav_list[i];  
  13.     //elemensArray.push(nav_list[i]); //同上一样的结果  
  14.      }  
  15.   return elemensArray;  
  16.    
  17. }  
  18. </script>  

正如看到的结果,IE和FireFox中都没有问题了。

精彩图集

赞助商链接