JavaScriptDOM文档遍历实战

在介绍了《JavaScript DOM修改文档树方法实例》与《JavaScript DOM实战:创建和克隆元素》,本文将介绍JavaScript DOM文档遍历的详细知识,我们先从HTML页面最基本的组成元素讨论起:

我们提供的服务有:成都网站设计、网站制作、微信公众号开发、网站优化、网站认证、池州ssl等。为近千家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的池州网站制作公司

 
 
 
  1.   

访问元素,你应该明白它是该文件的document元素,那你就可以使用document的documentElement属性:

 
 
 
  1. var oHtml=document.documentElement;//可以直接访问元素  
  2. alert("节点名称 : "+oHtml.nodeName);//节点名称  
  3. alert("节点类型 : "+oHtml.nodeType);//节点类型为 1  

获取 和 元素:

 
 
 
  1. var oHead=oHtml.firstChild;//HEAD节点  
  2. var oBody=oHtml.lastChild;//BODY节点  

也可以通过childNodes属性,获取 和 元素:

 
 
 
  1. var oHead=oHtml.childNodes.item(0);//HEAD节点  
  2. //var oHead=oHtml.childNodes[0];//简写,也有同样的结果是HEAD节点  
  3. var oBody=oHtml.childNodes.item(1);//BODY节点  
  4. //var oBody=oHtml.childNodes.item(1);//简写,也有同样的结果是BODY节点  

注意:方括号标记其实是NodeList在javascript中的简便实现。实际上正式的从childNodes列表中获取子节点的方法是使用item()方法:HTML DOM 中的专有属性 document.body ,它常用于直接访问元素:

 
 
 
  1. var oBody=document.body;  

既然我们都知道了以上节点对象的获取方式,那我们用oHtml,oHead,oBody 这三个变量来确定一下它们之间的关系:

 
 
 
  1. alert(oHead.parentNode==oHtml);//HEAD节点的父节点是BODY节点,返回 true   
  2. alert(oBody.parentNode==oHtml);//BODY节点的父节点是BODY节点,返回 true   
  3. alert(oBody.previousSibling==oHead);//BODY节点的上一个兄弟节点是HEAD节点 ,返回 true  
  4. alert(oHead.nextSibling==oBody);//HEAD节点的下一个兄弟节点是BODY节点,返回 true  
  5. alert(oHead.ownerDocument==document); //返回一个节点的根元素(Document),HEAD节点是否指向该文档,返回 true  

通过上面的学习我们已经了解遍历节点的最基本的方式, 也学会了如何找到某一个节点的兄弟节点及它的子节点。

#p#

复杂的节点遍历

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

 
 
 
  1.  
  2.     

    我的导航条

                
  3.      
  4.        
  5. HOME
  6.  
  7.        
  8. (X)Html / Css
  9.  
  10.        
  11. Ajax / RIA
  12.  
  13.        
  14. GoF
  15.  
  16.        
  17. JavaScript
  18.  
  19.        
  20. JavaWeb
  21.  
  22.        
  23. jQuery
  24.  
  25.        
  26. MooTools
  27.  
  28.        
  29. Python
  30.  
  31.        
  32. Resources
  33.  
  34.      
  

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

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

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

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

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

 
 
 
  1.  
  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
  14.     elemensArray[elemensArray.length]=nav_list[i];  
  15.     //elemensArray.push(nav_list[i]); //同上一样的结果  
  16.      }  
  17.   return elemensArray;  
  18.    
  19. }  
  20. /*  
  21. 我们观察到我的导航条是有规律的,是用无序列表元素组成的,只有定位到 <ul>元素  
  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
  31.   elemensArray[elemensArray.length]=nav_list[i];  
  32.   //elemensArray.push(nav_list[i]); //同上一样的结果  
  33.  }  
  34.  return elemensArray;  
  35.    
  36. }  
  37.   

节点遍历

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

 
 
 
  1.  
  2. window.onload=function(){  
  3.      /****个方法*/  
  4.      var list= queryElementsId();   
  5.   /*第二个方法*/  
  6.  //var list= queryElementsTagName();   
  7.  var s="";  
  8.  for(var i=0;i
  9.   s+=list[i].nodeName+"\n";   
  10.     }  
  11.  alert(s);  
  12.  }  
  13.   

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

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

方法一:

 
 
 
  1.  
  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.   

方法二:

 
 
 
  1.  
  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
  15.   if (childElem[i].nodeType==1){//把所有节点是元素节点类型的节点存放到数组里  
  16.    childElemArray.push(childElem[i]);   
  17.   }  
  18.  }  
  19.     return childElemArray;   
  20. }   
  21.   

方法三:推荐

 
 
 
  1.  
  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.   

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

 
 
 
  1.  
  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
  12.     elemensArray[elemensArray.length]=nav_list[i];  
  13.     //elemensArray.push(nav_list[i]); //同上一样的结果  
  14.      }  
  15.   return elemensArray;  
  16.    
  17. }  
  18.   

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

#p#

一个比较通用的方法:

 
 
 
  1.  
  2. function text(elem){  
  3.  var t="";  
  4.  //如果传入的是元素,则继续遍历其子元素  
  5.  //否则假定它是一个数组  
  6.  elemelem=elem.childNodes || elem;  
  7.  //遍历所有子节点  
  8.  for(var i=0; i
  9.      //如果不是元素,追加其文本值  
  10.   //否则,递归遍历所有元素的子节点  
  11.   t+=elem[i].nodeType !=1?elem[i].nodeValue:text(elem[i].childNodes);  
  12.    
  13.  }  
  14.     //返回比配的文本  
  15.     return t;  
  16. }  
  17.  

用元素节点的DOM属性遍历DOM树

 
 
 
  1.  
  2. window.onload=function(){  
  3.   /*定位想要的节点*/  
  4.   var nav=document.getElementById("nav");  
  5.   /*查找父节点*/  
  6.   var p_n=nav.parentNode;  
  7.   alert("父节点的元素名称:"+p_n.nodeName);  
  8.    
  9.   /*处理FF遍历节点中的#Text */  
  10.   removeWhitespace(nav);//移除所有的空Text节点  
  11.    
  12.   /*查找子节点*/    
  13.   var c_n_f=nav.firstChild;//***个节点对象  
  14.   //var c_n_f=nav.childNodes[0];//同上一样的结果  
  15.   var c_n_l=nav.lastChild;//***一个节点对象  
  16.   //var c_n_l=nav.childNodes[nav.childNodes.length-1];//同上一样的结果  
  17.   alert("***个节点:"+c_n_f.nodeName+"  "+"***一个节点 :"+c_n_l.nodeName);   
  18.   /*查找兄弟节点 或叫 相邻节点 */  
  19.   /*用nextSibling和PreviousSibling必须有一个参考点,这样指针才知道自己往那里移动*/  
  20.   var c_n_s=c_n_f.nextSibling;//***个节点的下一个节点  
  21.   alert("***个节点的下一个节点:"+c_n_s.innerHTML+ "\n" + "节点中包含的HTML内容: "+c_n_s.nodeName);  
  22.    
  23. }  
  24.  

写到这里,既然标准的previousSibling,nextSibling,firstChild,lastChild,parentNode遍历方法有浏览器不兼容问题。我上面的解决方案是去掉遍历元素的相关空的#Text节点,是一个好的解决方案,但是使用起来不方便,我们何不自己写一些遍历节点的方法来代替标准的的previousSibling,nextSibling,firstChild,lastChild,parentNode。

我们的思路是利用元素是nodeType属性来判断元素是节点类型中那种节点类型,在DOM节点中我最常用的是元素节点,文本节点,属性节点,对应的类型值是元素节点nodeType=1 or ELEMENT_NODE, 文本节点 nodeType=2 or ATTRIBUTE_NODE,属性节点 nodeType=3 or TEXT_NODE,但是IE中并不支持命名常量,那就用数值吧,再配合标准的遍历属性。完全可以自己生产一些辅助函数来取代标准的遍历方式。以下一系列的辅助函数可以帮助您,他们能取代标准的previousSibling,nextSibling,firstChild,lastChild,parentNode;

 
 
 
  1.  
  2. //---------DOM 遍历,如果元素没找到则返回null---------//      
  3.     //---查找相关元素的前一个兄弟元素---//      
  4.    function prev(elem){      
  5.         do{      
  6.            elemelem=elem.previousSibling;      
  7.         }while(elem && elem.nodeType!=1);      
  8.         return elem;      
  9.     }      
  10.     //---查找相关元素的下一个兄弟元素---//      
  11.     function next(elem){      
  12.        do{      
  13.            elemelem=elem.nextSibling;      
  14.         }while(elem && elem.nodeType!=1);      
  15.         return elem;      
  16.     }      
  17.     //---查找***个子元素的函数---//      
  18.     function first(elem){      
  19.         elemelem=elem.firstChild;      
  20.         return elem && elem.nodeType!=1 ?next(elem):elem;      
  21.     }      
  22.     //---查找***一个子元素的函数---//      
  23.     function last(elem){      
  24.         elemelem=elem.lastChild;      
  25.         return elem && elem.nodeType!=1 ?prev(elem):elem;      
  26.     }      
  27.     //---查找父级元素的函数---//      
  28.     //num是父级元素的级次,parent(elem,2)等价于  
  29.    function parent(elem,num){      
  30.         numnum=num||1;      
  31.         for(var i=0; i
  32.             if(elem!=null){      
  33.                 elemelem=elem.parentNode;      
  34.            }      
  35.         }      
  36.        return elem;      
  37.    }   
  38.  

原文链接:http://cssrainbow.cn/tutorials/javascript/565.html

【编辑推荐】

  1. JavaScript DOM特性与应用详解
  2. JavaScript DOM修改文档树方法实例
  3. JavaScript DOM实战:创建和克隆元素 

当前标题:JavaScriptDOM文档遍历实战
标题来源:http://www.shufengxianlan.com/qtweb/news26/246076.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

猜你还喜欢下面的内容

ChatGPT知识

同城分类信息