zoukankan      html  css  js  c++  java
  • 选取文档元素的API


    除了现在常用的选取API
    1 document.getElementById()
    2 document.getElementsByName()
    3 document.getElementsByTagName()
    4 ...

     新增的API 主要是
      document.querySelector('div>ul')
      document.querySelectorAll('div>ul>li')
         这两个API的强大之处在于能像CSS选择器一样选择元素,和Jquery的选择器有的一拼

    <!DOCTYPE html>
    <html>
    <head lang="en">
    <meta charset="UTF-8">
    <title></title>
    </head>
    <body>
    <div>
    <ul>
    <li></li>
    <li class="abc"></li>
    <li class="bbb abc"></li>
    </ul>
    </div>
    <div>
    <p>11111111111111
    </p>
    </div>
    </body>
    <script>
    var a=document.querySelectorAll('div>ul')[0]
    console.log(a.childElementCount) // 3
    var b=document.createElement('li');
    b.textContent='44444';
    a.appendChild(b)
        console.log(a.childElementCount) //3
    console.log(document.querySelectorAll('div>ul>li').length) //4
    </script>
    </html>


    以下介绍下他们的不同点:
        document.querySelector()
            返回的是第一个匹配的元素(以文档顺序)
            匹配不到则返回null
       document.querySelectorAll()
           返回的是一个表示文档中匹配选择器的所有元素的NodeList对象(显然该对象是一个集合),
           这个NodeList对象并不是实时的:它包含在调用时刻选择器锁匹配的元素,但并不更新后续文档的变化(详见上面实列)
           匹配不到则返回一个空的NodeList对象
          选择器非法 将抛出异常
    另外一点是这两个方法在Element节点中也有定义 (DocumentFragment节点上也是有定义的)
    如:

         var d=document.getElementsByTagName('div')[0].querySelector('.abc')
         console.log(d.textContent)

    目前支持这两个API 有:IE8+,Firefox 3.5+,Safari 3.1+,Chrom 和Opera 10+

    有一个小问题:
        <div id="abcdefg">
                    <p>11111111111111
                   </p>
        </div>
         var c=document.querySelector('#abcdefg');
         console.log(c.querySelector('div p').innerHTML); // 这个是能找到值的
       理想情况是 在id为abcdefg 的内部查找 div 下面的p元素,显示出p的innerHTML 应该是找不到的
       但是现在却打印出来了 It's a problem; 查询时也必要这样查询
       应该一次性写出来: document.querySelector('#abcdefg div p'); 会报异常 因为找不到

    性能问题:

           通过对1千万次的读取发现getElementBy系列的查询速度要远高与 queryselector系列

     1  var begin = new Date();
     2     for (var i = 0; i < 10000000; i++) {
     3 
     4         var a=document.getElementById('abc');
     5 
     6     }
     7     var end= new Date();
     8     console.log(end-begin);
     9     var begin1 = new Date();
    10     for (var i = 0; i < 10000000; i++) {
    11 
    12         var a=document.querySelector('#abc');
    13 
    14     }
    15     var end1=new  Date();
    16     console.log(end1-begin1);

       究其原因发现 主要是因为queryselectorall  返回的nodeList是静态的 而getElementBy 系列返回的是动态的  细化一下主要是:

             在深入了解细节之前,首先说下这俩个方法重要的区别,不仅仅是一个方法接受tagName,另外一个接受css选择器。最重要的区别在于返回值: getElementsByTagName() 返回一个实时的 NodeList,
    querySelectorAll()返回静态的 NodeList。 这点是对理解速度的快慢是非常重要的。实时的NodeList 这个是文档对象模型(Document Object Model)的一个坑。 NodeList对象(也就是在HTML DOM中的HTMLCollection对象)是个特殊的类型。DOM3手册对HTMLCollection对象的规定如下:

            Nodelist跟NamedNodeMap对象在DOM中是实时的;也就是说,对基本文档结构的修改,会被映射到相关的Nodelist跟NameNodeMap对象。例如,如果一个DOM的用户得到了包含有子元素节点的NodeList对象,随后在这个元素上添加更多的子节点(或者是移除,或者是修改他们),这些改变会自动映射到NodeList对象中,不需要用户部分的额外操作。同样的,改变在树中的节点,也会自动映射到跟这个节点有关的
    NodeList跟NamedNodeMap中的对象。
    getElementsByTagName()方法,返回这些实时的元素集合-随着文档的改变而更新。因此,下边这段代码其实是个死循环:

     1 var divs = document.getElementsByTagName("div"),
     2 i=0;
     3 while(i < divs.length){
     4 document.body.appendChild(document.createElement("div"));
     5 i++;
     6 }

    因为divs.lenght实时计算的原因,所以这是个死循环。每次迭代,添加一个新的div,意味着divs.length每次循环都会增加。

    这些实时的集合,看起来像个坏主意,但是他们被放到document.images,document.forms这些方法中,跟其他的一些pre-DOM的集合中使用相同的对象,在浏览器中非常常见。

      静态的NodeList
            querySelectorAll()返回的是静态的NodeList,描述如下:被querySelectorAll() 返回的对象必须(must)是静态的,非实时的([DOM-LEVEL-3-CORE],1.1.1部分)。后来的对文档的改变,不能(must not)反应到NodeList对象上。这意味着,此对象实际上包含的是文档刚创建的时候,查询到的匹配的列表。所以,即使querySelectorAll()的返回值跟表现,同getElementsByTagName()是一样的,但是实际上,他们是不同的。在前者中,NodeList实际上是一个文档状态,在方法被调用时刻的快照,后者总是会更新到当前的状态。所以,下边的代码不是死循环:

     1 var divs = document.querySelectorAll("div"),
     2 i=0;
     3 while(i < divs.length){
     4 document.body.appendChild(document.createElement("div"));
     5 i++;
     6 }

    div.length 不会改变。

       So为啥是实时的NodeLists更快呢?
           实时的NodeLit对象能够快速的被浏览器创建,并返回,因为他们他们不必知道从开始到现在的数据信息,但是,静态的需要收集这些信息。再此强调下,WebKit的源码对两中类型的NodeList有独立的文件:DynamicNodeList.css跟StaticNodeList.cspp.两种类型的对象以不同的方式被创建。DynamicNodelist是被注册到缓存中。本质上,创建DynamicNodelist开销是比较小的,因为他不会之前的事情。无论何时DynamicNodeList被访问的时候,它必须查询文档的改变,作为length属性跟item()方法的结果跟StaticNodeList比较,在另外一个文件中实例被创建,然后用内部的一个循环,进行数据填充。之前文档查询的开销比使用”DynamicNodeList”实例大的多。如果你看一下WebKit的源码,创建querySelectorAll()的返回值的时候,都是使用循环去创建这个结果。

      结论:
         getElementsByTagName()比querySelectorAll()快的原因是,实时跟静态NodeList对象引起的。
         决定使用哪个方法,主要取决于你想要什么。如果你通过tagName搜索元素,不需要快照,应该使用getElementsByTagName();如果你需要一个快照结果,或者是做一个更复杂的css查询,应当使用
    **querySelectorAll()*

        注,部分文档摘录自:

          http://www.cnblogs.com/dolphinX/p/3354318.html

            http://www.heyria.com/index.php/2014/06/why-is-getelementsbytagname-faster-that-queryselectorall/

    
    
    
    




     



         

      
  • 相关阅读:
    dapper 批量删除、新增、修改说明
    android 加载assets目录下的静态html文件案例
    webstorm中使用git提交代码时出现unversioned files错误
    windows server 2008 R2 x64 部署.net core 3.1项目
    asp.net core 项目添加nlog日志(loggerFactor.AddNLog 过时处理(.net core 3.1))
    机器学习笔记之一步步教你轻松学主成分分析PCA降维算法
    机器学习笔记之类别特征处理
    机器学习笔记之range, numpy.arange 和 numpy.linspace的区别
    机器学习笔记之Numpy的random函数
    机器学习笔记之矩阵分解 SVD奇异值分解
  • 原文地址:https://www.cnblogs.com/ArthurXml/p/5387637.html
Copyright © 2011-2022 走看看