• JavaScript DOM 选择器 querySelector


    W3C的规范与库中的实现

    querySelectorreturn the first matching Element node within the node’s subtrees. If there is no such node, the method must return null .(返回指定元素节点的子树中匹配selector的集合中的第一个,如果没有匹配,返回null)

    querySelectorAllreturn a NodeList containing all of the matching Element nodes within the node’s subtrees, in document order. If there are no such nodes, the method must return an empty NodeList. (返回指定元素节点的子树中匹配selector的节点集合,采用的是深度优先预查找;如果没有匹配的,这个方法返回空集合)

    querySelector 和 querySelectorAll 的使用非常的简单,它和 CSS 的写法完全一样。假如我们有一个 id 为 test 的 DIV,为了获取到这个元素,你也许会像下面这样:

    document.getElementById("test");

    现在我们来试试使用新方法来获取这个 DIV:

    document.querySelector("#test");
    document.querySelectorAll("#test")[0];

     

    感觉区别不大是吧,但如果是稍微复杂点的情况,原始的方法将变得非常麻烦,这时候 querySelector 和 querySelectorAll 的优势就发挥出来了。比如接下来这个例子,我们将在 document 中选取 class 为 test 的 div 的子元素 p 的第一个子元素,当然这很拗口,但是用本文的新方法来选择这个元素,比用言语来描述它还要简单。

    document.querySelector("div.test>p:first-child");
    document.querySelectorAll("div.test>p:first-child")[0];

     

    现在应该对于 querySelector、querySelectorAll 方法中的参数已经非常明白了,它接收的参数和 CSS 选择器完全一致。querySelector 和 querySelectorAll 的区别在于 querySelector 用来获取一个元素,而 querySelectorAll 可以获取多个元素。querySelector 将返回匹配到的第一个元素,如果没有匹配的元素则返回 Null。querySelectorAll 返回一个包含匹配到的元素的数组,如果没有匹配的元素则返回的数组为空。在本文最后一个例子中,我们使用 querySelectorAll 给所有 class 为 emphasis 的元素加粗显示。

    var emphasisText = document.querySelectorAll(".emphasis");
    for( var i = 0 , j = emphasisText.length ; i < j ; i++ ){
        emphasisText[i].style.fontWeight = "bold";
    }

    这是原生方法,比起jquery速度快,缺点是IE6、7不支持。

     

    这在BaseElement 为document的时候,没有什么问题,各浏览器的实现基本一致;但是,当BaseElement 为一个普通的dom Node的时候(支持这两个方法的dom Node ),浏览器的实现就有点奇怪了,举个例子:

    <div class= "test"   id= "testId" > 
         <p><span>Test</span></p> 
    </div> 
    <script type= "text/javascript" >     
         var   testElement= document.getElementById( 'testId' );  
         var   element = testElement.querySelector( '.test span' );  
         var   elementList = document.querySelectorAll( '.test span' );  
         console.log(element);  // <span>Test</span>
         console.log(elementList);  // 1    
    </script>

    按照W3C的来理解,这个例子应该返回:element:null;elementList:[];因为作为baseElement的 testElement里面根本没有符合selectors的匹配子节点;但浏览器却好像无视了baseElement,只在乎selectors,也就是说此时baseElement近乎document;这和我们的预期结果不合,也许随着浏览器的不断升级,这个问题会得到统一口径!

    人的智慧总是无穷的,Andrew Dupont发明了一种方法暂时修正了这个怪问题,就是在selectors前面指定baseElement的id,限制匹配的范围;这个方法被广泛的应用在各大流行框架中;

    Jquery的实现:

    var   oldContext = context,
    old = context.getAttribute(  "id"   ),
    nid = old || id,
    
    try   {
    	if   ( !relativeHierarchySelector || hasParent ) {
         	return   makeArray( context.querySelectorAll(  "[id='"   + nid +  "'] "   + query ), extra );
      	}    
    }  
    catch (pseudoError) {} 
    finally {
    	if   ( !old ) {
    	 	oldContext.removeAttribute(  "id"   );
    	}
    }

    先不看这点代码中其他的地方,只看他如何实现这个方法的;这点代码是JQuery1.6的片段;当baseElement没有ID的时候,给他设置一个id = "__sizzle__”,然后再使用的时候加在selectors的前面,做到范围限制;context.querySelectorAll( "[id='" + nid + "'] " + query ;最后,因为这个ID本身不是baseElement应该有的,所以,还需要移除:oldContext.removeAttribute( "id" ); ,Mootools的实现:

    var   currentId = _context.getAttribute( 'id' ), slickid =  'slickid__' ;
    _context.setAttribute( 'id' , slickid);
    _expression =  '#'   + slickid +  ' '   + _expression;
    context = _context.parentNode;

    Mootools和Jquery类似:只不过slickid = 'slickid__';其实意义是一样的;方法兼容性:FF3.5+/IE8+/Chrome 1+/opera 10+/Safari 3.2+;IE 8 :不支持baseElement为object。

    文章来源:原生的强大DOM选择器querySelector

  • 相关阅读:
    dataTables的导出Excel功能
    jquery生成二维码图片
    angular2表单初体验
    台湾辅仁大学的python教程笔记
    浅说《测试用例》----给测试新手的
    测试员的工作与学习
    简单的表格代码
    特殊效果字体代码
    办公自动化的基本方法
    css网页的几种类型
  • 原文地址:https://www.cnblogs.com/xiaochechang/p/5779048.html
Copyright © 2020-2023  润新知