在传统的 JavaScript 开发中,查找 DOM 往往是开发人员遇到的第一个头疼的问题,原生的 JavaScript 所提供的 DOM 选择方法并不多,仅仅局限于通过 tag, name, id 等方式来查找,这显然是远远不够的,如果想要进行更为精确的选择不得不使用看起来非常繁琐的正则表达式,或者使用某个库。事实上,现在所有的浏览器厂商都提供了 querySelector 和 querySelectorAll 这两个方法的支持,甚至就连微软也派出了 IE 8 作为支持这一特性的代表,querySelector 和 querySelectorAll 作为查找 DOM 的又一途径,极大地方便了开发者,使用它们,你可以像使用 CSS 选择器一样快速地查找到你需要的节点。

querySelector 和 querySelectorAll 的使用非常的简单,就像标题说到的一样,它和 CSS 的写法完全一样,对于前端开发人员来说,这是难度几乎为零的一次学习。假如我们有一个 id 为 test 的 DIV,为了获取到这个元素,你也许会像下面这样:

document.getElementById("test");

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

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

下面是个小演示:

我是 id 为 test 的 div

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

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

下面是个小演示:

我是层里的 p 标签

现在应该对于 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不支持。

W3C的规范与库中的实现

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

querySelectorAll:return 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的节点集合,采用的是深度优先预查找;如果没有匹配的,这个方法返回空集合)

这在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;

querySlector的更多相关文章

  1. getElementById() getElementsByTagName() getElementsByClassName() querySlector() querySlectorAll()区别

    1. getElementById() getElementsByTagName()  javascript原生的方法,这两个不会有兼容性问题. 2. getElementsByClassName() ...

  2. js011-DOM扩展

    js011-DOM扩展 本章内容 理解Selecters API 使用HTML5 DOM扩展 了解转悠的DOM扩展 11.1选择符API JS中最常用的一项功能,就是根据css选择符选择与某个模式匹配 ...

  3. javascript入门知识点总结(一)

    学了几天javascript,现总结一下原生javascript的基本知识点. 一.javascript基本知识 变量 定义: var a = 123; var b = 'abc'; //连写 var ...

  4. python基础整理3——前端

    html概述和基本结构 html概述 HTML意思是超文本标记语言 html基本结构 一个html的基本结构如下: <!DOCTYPE html> <html lang=" ...

  5. JS——两个原生选择器

    1. document.querySlector() 2.document.querySlectorAll() <!DOCTYPE html> <html lang="en ...

  6. 关于JavaScript 基础总结

    Dom:document object model 即文档对象模型 Bom: browser object model 即浏览器对象模型 文档对象模型即与文本密切相关,比如document.query ...

  7. 【JavaScript】JS从入门到深入(复习查漏向

    [JavaScript]JS从入门到深入(复习查漏向 pre 精细得学过一遍JS后才发现,原来之前CTF中有些nodejs的题目以及一些游戏题的payload就变得很好理解了. 基础知识 ECMASc ...

随机推荐

  1. java反射的理解与应用(某大神博客中看到的博文,写的真的太好了,果断转载作为笔记)

    原文地址:http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html#undefined 一.什么是反射机制 简单的来说,反射机制指的是程序 ...

  2. 转: 尽己力,无愧于心 FastReport.Net 常用功能总汇

    FastReport.Net 常用功能总汇   一.常用控件 文本框:输入文字或表达式 表格:设置表格的行列数,输入数字或表达式 子报表:放置子报表后,系统会自动增加一个页面,你可以在此页面上设计需要 ...

  3. 细说Asp.Net WebAPI消息处理管道

    我们在开发完Asp.Net WebAPI程序后,可以使用WebHost寄宿方式或者SelfHost寄宿方式来部署Asp.Net WebAPI.所谓WebHost寄宿就是通过Asp.Net来实现:所谓S ...

  4. 如何写好 Git commit messages

    导语:任何软件项目都是一个协作项目,它至少需要2个开发人员参与,当原始的开发人员将项目开发几个星期或者几个月之后,项目步入正规.不过他们或者后续的开发人员仍然需要经常提交一些代码去修复bug或者实现新 ...

  5. HR从业者的下一个十年该怎么做?

    众所周知,目前我们所处的以互联网为代表的新经济时代,有两个重要的特征一是客户价值至上,二是人力资本主权.围绕这两个基本特征,我们需要重新架构我们的商业模式和创新人力资源管理思维.模式.工具和方法. 人 ...

  6. PHP基础学习(函数一)

    PHP(Hypertext Preprocessor):超文本预处理器,一种嵌入在HTML中并且运行在服务器端的脚本语言. var_dump--打印变量相关信息 说明:  <?php var_d ...

  7. 解析java泛型(二)

    上篇我们简单的介绍了java中泛型的最基本的内容,知道了什么是泛型以及泛型对我们的程序编写有什么好处,最后一类型限定收尾.本篇将从类型限定开始阐述java泛型中很重要的概念:通配符 一.何为通配符   ...

  8. 第28篇 js中let和var

      let与var 在js中声明一个变量除了一个var 还有一个let的声明.对于var 在前面的作用域中已经讲过,这次主要说下二者的区别: 在MDN上有这样的一个demo: var list = d ...

  9. Smarty模板的基础

    对前后端进行分离 如果要用的话,要从网上把smarty文件下载下来,才能用 smarty的核心是一个类 建一个php文件,写一个类文件 <?php class smarty { public $ ...

  10. mfc---手动给toolbar按钮添加消息View中

    手动给toolbar按钮添加消息View中: .h: afx_msg void OnButtonBG(); .cpp: ON_COMMAND(ID_BUTTON_BG,OnButtonBG) .cpp ...