设为首页收藏本站

就爱编程论坛

 找回密码
 注册

人人连接登陆

无需注册,直接登录

用新浪微博连接

一步搞定

QQ登录

只需一步,快速开始

查看: 526|回复: 4
打印 上一主题 下一主题

用JS遍历DOM(使用NodeIterator和TreeWalker) [复制链接]

Rank: 9Rank: 9Rank: 9

  • TA的每日心情
    无聊
    2025-5-27 03:37:20
  • 签到天数: 366 天

    [LV.9]以坛为家II

    论坛先锋 学习至圣 荣誉成员 论坛元老 活跃之星 终极领袖

    我玩的应用:

    跳转到指定楼层
    楼主
    发表于 2011-7-13 03:32:06 |只看该作者 |倒序浏览
    首先声明NodeFilter在IE中不能使用,所有最好使用火狐对下面代码进行测试!
    第一种方法:使用NodeIterator
    可以用document对象的createNodeIterator()方法来创建NodeIterator对象,基本形式如下:
    var iterator = document.createNodeIterator(root, whatToShow, filter, entityReferenceExpansion);
    用到的四个参数意义如下:
    1、root:从树中的哪个节点开始搜索;
    2、whatToShow:一个数值代码,代表哪些节点需要搜索;
    3、filter:NodeFilter对象,用来决定需要忽略哪些节点;
    4、entityReferenceExpansion:布尔值,表示是否需要扩展实体引用;
    whatToShow参数可以有下列这些常量或其组合的取值:
    1、NodeFilter.SHOW_ALL:搜索所有节点;
    2、NodeFilter.SHOW_ELEMENT:搜索元素节点;
    3、NodeFilter.SHOW_ATRRIBUTE:搜索特性节点;
    4、NodeFilter.SHOW_TEXT:搜索文本节点;
    5、NodeFilter.SHOW_ENTITY_REFERENCE:搜索实体引用节点;
    6、NodeFilter.SHOW_ENTITY:搜索实体节点;
    7、NodeFilter.SHOW_PROCESSING_INSTRUCTION:搜索PI节;
    8、NodeFilter.SHOW_COMMENT:搜索注释节点;
    9、NodeFilter.SHOW_DOCUMENT:搜索文档节点;
    10、NodeFilter.SHOW_DOCUMENT_TYPE:搜索文档类型节点;
    11、NodeFilter.SHOW_DOCUMENT_FRAGMENT:搜索文档碎片节节;
    12、NodeFilter.SHOW_NOTATION:搜索记号节点;
    可以使用二进制操作来组合多个值:
    var whattoshow = NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT;
    常用的有按位或运算符"|"和按位取补运算符"~";
    filter参数可以指定一个自定义的NodeFilter对象,但如果不想使用它的话,也可以留空(null);
    要创建最简单的访问所有节点的NodeIterator对象,可以使用下面的代码:
    var iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL, null, false);
    要在搜索过程中前进或者后退,可以使用nextNode()和previousNode()方法:
    var node1 = iterator.nextNode();
    var node2 = iterator.nextNode();
    var node3 = iterator.previousNode();
    alert(node1 == node3);输出结果为“true”;
    例如,想列出某个区域内指定<div />中包含的所有元素。下列代码可以完成这个任务:
    <html>
    <head>
    <title>dom中的NodeIterator对象示例</title>
    <script>
    function makelist()
    {
       var divnode = document.getElementByIdx("div1");
      
       var iterator = document.createNodeIterator(divnode, NodeFilter.SHOW_ELEMENT, null, false);
       var oput = document.getElementByIdx("textarea1");
       var node = iterator.nextNode();
       while(node)
       {
          oput.value += node.tagName +"\n";
          node = iterator.nextNode();
       }
    }
    </script>
    </head>
    <body>
    <div id="div1">
       <p>你好<b>读者!</b></p>
       <ul>
          <li>列表项一</li>
          <li>列表项二</li>
          <li>列表项三</li>
          <li>列表项四</li>
       </ul>
    </div>
    <textarea id="textarea1" rows="10"></textarea><br />
    <input type="button" value="生成列表" />
    </body>
    </html>
    但假设不想在结果中包含<p />元素。这就不能公用whatToShow参数来完成。这种情况下,就要用到filter参数,而filter参数需要自定义一个NodeFilter对象,该对象只有一个方法acceptNode()。如果应该访问给定的节点,那么该方法返回NodeFilter.FILTER_ACCEPT;如果不应该访问该节点并且其子节点也没兴趣,则返回NodeFilter.FILTER_REJECT;如果不应该访问该节点但仍对其子节点有兴趣,则返回NodeFilter.FILTER_SKIP。代码如下:
    <html>
    <head>
    <title>dom中的NodeIterator对象示例</title>
    <script>
    function makelist()
    {
       var divnode = document.getElementByIdx("div1");
       var filter = new Object();
       filter.acceptNode = function(node)
       {
          return (node.tagName == "P") ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT;
       }
       var iterator = document.createNodeIterator(divnode, NodeFilter.SHOW_ELEMENT, FILTER, false);
       var oput = document.getElementByIdx("textarea1");
       var node = iterator.nextNode();
       while(node)
       {
          oput.value += node.tagName +"\n";
          node = iterator.nextNode();
       }
    }
    </script>
    </head>
    <body>
    <div id="div1">
       <p>你好<b>读者!</b></p>
       <ul>
          <li>列表项一</li>
          <li>列表项二</li>
          <li>列表项三</li>
          <li>列表项四</li>
       </ul>
    </div>
    <textarea id="textarea1" rows="10"></textarea><br />
    <input type="button" value="生成列表" />
    </body>
    </html>

    第二种方法使用TreeWalker遍历DOM文档
    TreeWalker有点向NodeIterator的大哥一样:它有NodeIterator所有的功能,并且添加了下面一些遍历方法:
    parentNode():进入当前节点的父节点;
    firstChild():进入当前节点的第一子节点;
    lastChild():进入当前节点的最后一个子节点
    nextSibling():进入当前节点的下一个兄弟节点
    previousSibling():进入当前节点的前一个兄弟节点
    要开始使用TreeWalker,其实完全可以向使用NodeIterator一样,只需要将createNodeIterator()改成createTreeWalker()即可,这个函数接收同样的参数:

    <html>
    <head>
    <title>dom中的NodeIterator对象示例</title>
    <script>
    function makelist()
    {
       var divnode = document.getElementByIdx("div1");
       var filter = new Object();
       filter.acceptNode = function(node)
       {
          return (node.tagName == "P") ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT;
       }
       var iterator = document.createTreeWalker(divnode, NodeFilter.SHOW_ELEMENT, FILTER, false);
       var oput = document.getElementByIdx("textarea1");
       var node = iterator.nextNode();
       while(node)
       {
          oput.value += node.tagName +"\n";
          node = iterator.nextNode();
       }
    }
    </script>
    </head>
    <body>
    <div id="div1">
       <p>你好<b>读者!</b></p>
       <ul>
          <li>列表项一</li>
          <li>列表项二</li>
          <li>列表项三</li>
          <li>列表项四</li>
       </ul>
    </div>
    <textarea id="textarea1" rows="10"></textarea><br />
    <input type="button" value="生成列表" />
    </body>
    </html>

    也可以使用TreeWalker特有的方法来准确的定位DOM文档的某一个节点:如获取<LI>节点

    <html>
    <head>
    <title>dom中的NodeIterator对象示例</title>
    <script>
    function makelist()
    {
        var oDiv = document.getElementByIdx("div1");
         var oFilter = new Object;
         oFilter.acceptNode = function(oNode){
           return (oNode.tagName=="P")?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT;
         };
         var walker = document.createTreeWalker(oDiv,NodeFilter.SHOW_ELEMENT,oFilter,false);
         var oOutput = document.getElementByIdx("text1");
         var oP = walker.firstChild(); //go to <p>
         var oUl = walker.nextSibling(); // go to <ul>
         var oLi = walker.firstChild();  //go to <li>
         while(oLi){
            oOutput.value += oLi.tagName + "\n";
            oLi = walker.nextSibling();
         }
    }
    </script>
    </head>
    <body>
    <div id="div1">
       <p>你好<b>读者!</b></p>
       <ul>
          <li>列表项一</li>
          <li>列表项二</li>
          <li>列表项三</li>
          <li>列表项四</li>
       </ul>
    </div>
    <textarea id="textarea1" rows="10"></textarea><br />
    <input type="button" value="生成列表" />
    </body>
    </html>
    分享到: QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    分享分享0 收藏收藏0 支持支持0 反对反对0 分享到人人 转发到微博
    [img=http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=fRUcHhYWGAQ9GxIFEBwUEVMeEhA]http://rescdn.qqmail.com/zh_CN/htmledition/images/function/qm_open/ico_mailme_02.png[/img]

    使用道具 举报

    Rank: 2

    升级 
     
    36%

    该用户从未签到

    沙发
    发表于 2011-9-14 14:19:37 |只看该作者

    使用道具 举报

    Rank: 3Rank: 3

    升级 
     
    52.33%

    该用户从未签到

    板凳
    发表于 2011-9-15 21:02:31 |只看该作者
    哪个呦,发这么好的帖子,顶你












    1.80战神复古 1.80战神复古 1.80战神合击

    使用道具 举报

    Rank: 2

    升级 
     
    50%

    该用户从未签到

    地板
    发表于 2011-9-26 20:24:48 |只看该作者
    好贴子哦,大家不顶说不过去













    使用道具 举报

    Rank: 3Rank: 3

    升级 
     
    46.33%

    该用户从未签到

    5#
    发表于 2011-10-13 18:56:50 |只看该作者

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册 人人连接登陆

    晴云孤魂's Blog|就爱编程搜帖|手机版|Archiver|就爱编程论坛     

    GMT+8, 2025-7-5 01:44 , Processed in 0.100678 second(s), 35 queries .

    Powered by Discuz! X2

    © 2001-2011 Comsenz Inc.

    回顶部