• DOM2级提供的对DOM结构执行深度优先遍历 笔记


      NodeIterator和TreeWalker这2个类型可以基于给定的起点对DOM结构执行深度优先遍历。(我测试用的浏览器是Chrome,介绍说IE不支持DOM遍历,但是不知道最新的IE支持不支持)

      1、NodeIterator

        使用document.createNodeIterator()方法创建新实例,该方法接受4个参数:

          (1)、root:要访问的树的根节点。

          (2)、whatToShow:要访问的节点的数字代码。

          (3)、filter:是一个NodeFilter对象,或者一个表示过滤特定节点的函数。

          (4)、entityReferenceExpansion:布尔值,表示是否要扩展实体引用。

        whatToShow参数是一个位掩码,通过应用1或多个过滤器来确定要访问哪些节点。这个参数的值以常量的形式在NodeFilter类型中定义,具体的可以搜一下,同事可以使用"||"操作符来组合多个选项。

        Filter参数用来自定义NodeFilter对象,或者指定一个过滤特定节点的函数。每个NodeFilter对象只有一个方法,即acceptNode();如果访问了给定的节点,该方法返回NodeFilter.FILTER_ACCEPT,如果访问了未给定的节点,该方法返回NodeFilter.FILTER_SKIP。由于NodeFilter是一个抽象的类型,因此不能直接创建它的实例。只要创建一个包含acceptNode()方法的对象,然后将这个对象传入createNodeIterator()中即可。

        例如,下列代码展示了创建一个只显示<p>元素的节点迭代器:

        var filter = {
            acceptNode: function(node) {
                return node.tagName.toLowerCase() == 'p' ?
                           NodeFilter.FILTER_ACCEPT :
                           NodeFilter.FILTER_SKIP;
            }
        };
    
        var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT, filter, false);

        第三个参数也可以是一个与acceptNode()方法类似的函数,如下:

         var filter = function(node) {
            return node.tageName.toLowerCase == 'p' ?
                       NodeFilter.FILTER_ACCEPT :
                       NodeFilter.FILTER_SKIP;
            }
        };
    
        var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT, filter, false);

        如果不指定过滤器,那么第三个参数就设置为null。

        NodeIterator类型的两个主要方法是nextNode()和previousNode()。在新创建的NodeIterator对象中,有一个内部指针指向根节点,第一次调用nextNode()会返回根节点。当遍历到DOM子树的最后一个节点时,nextNode()返回null。同理,当遍历到DOM子树的最后一个节点,且previousNode()返回根节点之后,再次调用它就会返回null。

        

        假设有如下一段代码,我们要去除里面每一个<li>节点

      <div id="div1">
          <div></div>
          <ul>
              <li>0</li>
              <li>1</li>
              <li>2</li>
              <li>3</li>
              <li>4</li>
              <li>5</li>
              <li>6</li>
          </ul>
      </div>
      <script>
           var div = document.getElementById('div1');
           var filter = function(node) {
               return node.tagName.toLowerCase() == 'li' ? NodeFilter.FILTER_ACCEPT :NodeFilter.FILTER_SKIP;
           };
    
           var iterator = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT, filter, false);
    
           var node = iterator.nextNode();
           var nodes = [];
           while (node !== null) {
               nodes.push(node.tagName.toLowerCase());
               node = iterator.nextNode();
           }
           console.log(nodes);
      </script>

        

      2、TreeWalker

        TreeWalker是NodeIterator的一个更高级的版本。除了包括nextNode()和previousNode()在内的相同功能之外,该类型还提供了下列方法:

          (1)、parentNode():遍历到当前节点的父节点。

          (2)、firstChild():遍历到当前节点的第一个子节点。

          (3)、lastChild():遍历到当前节点的最后一个子节点。

          (4)、nextSibling():遍历到当前节点的下一个兄弟节点。

          (5)、previousSibling():遍历到当前节点的上一个兄弟节点。

        创建TreeWalker对象要使用document.createTreeWalker()方法,该方法接受4个参数(与document.createNodeIterator()方法相同):作为遍历起点的根节点、要显示的节点类型、过滤器和一个表示是否扩展实体引用的布尔值。

        基础的使用和document.createNodeIterator()很相似:

        var filter = {
            acceptNode: function(node) {
                return node.tagName.toLowerCase() == 'p' ?
                           NodeFilter.FILTER_ACCEPT :
                           NodeFilter.FILTER_SKIP;
            }
        };
    
        var iterator = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, filter, false);

        filter的返回值除了NodeFilter.FITLER_ACCEPT和NodeFilter.FILTER_SKIP之外,还可以使用NodeFilter.FILTER_REJECT。在使用NodeFitler对象时,NodeFilter.FILTER_SKIP和NodeFitler.FILTER_REJECT的作用相同:跳过指定节点。但在使用TreeWalker对象时,NodeFilter.FILTER_SKIP会跳过相应节点继续前进到该节点的子树的下一个节点;而NodeFilter.FILTER_REJECT则会跳过相应节点及该节点的整个子树。

        当然,TreeWalker真正强大的地方在于能够在DOM结构中沿任何方向移动。

    <div id="div1">
        <div></div>
        <ul>
            <li>0</li>
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
            <li>6</li>
        </ul>
    </div>
    
    <script>
        var div = document.getElementById('div1');
        var walker = document.createTreeWalker(div, NodeFilter.SHOW_ELEMENT, null, false);
    
        walker.firstChild();  //转到<div>
        walker.nextSibling();  //转到<ul>
    
        var node = walker.firstChild();  //转到第一个<li>
        var nodes = [];
        while (node !== null) {
            nodes.push(node.tagName.toLowerCase());
            node = walker.nextSibling();
        }
        console.log(nodes);
    </script>

        

        TreeWalker类型还有一个属性,叫做currentNode,表示任何遍历方法在上一次遍历中返回的节点。通过设置这个属性也可以修改遍历继续进行的起点。

        

  • 相关阅读:
    【Android】Handler的应用(二):从服务器端加载JSON数据的优化
    [置顶] IOS 开发之 CocoaPods讲解
    POJ 1068 (13.10.11)
    android使用百度地图、定位SDK实现地图和定位功能!(最新、可用+吐槽)
    C++笔记(1)
    WCF讲解
    php5 图片验证码一例
    PHP5 GD库生成图形验证码(汉字)
    mysql中limit的用法实例解析
    Limit参数优化MySQL查询的方法
  • 原文地址:https://www.cnblogs.com/youyouluo/p/5985632.html
Copyright © 2020-2023  润新知