各浏览器中querySelector和querySelectorAll的实现差异分析


Posted in Javascript onMay 23, 2012

querySelector和querySelectorAll是W3C提供的新的查询接口

querySelector和querySelectorAll是W3C提供的 新的查询接口,其主要特点如下:

1、querySelector只返回匹配的第一个元素,如果没有匹配项,返回null。
2、querySelectorAll返回匹配的元素集合,如果没有匹配项,返回空的nodelist(节点数组)。
3、返回的结果是静态的,之后对document结构的改变不会影响到之前取到的结果。

这两个方法都可以接受三种类型的参数:id(#),class(.),标签,很像jquery的选择器。

var obj = document.querySelector("#id");var obj = document.querySelector(".classname");
var obj = document.querySelector("div");
var el = document.body.querySelector("style[type='text/css'], style:not([type])");
var elements = document.querySelectorAll("#score>tbody>tr>td:nth-of-type(2)");
var elements = document.querySelectorAll("#id1, #id2, .class1, class2, div a, #list li img");

目前IE8+,ff,chrome都支持此api(IE8中的selector string只支持css2.1的)
浏览器支持查看

module dom {
[Supplemental, NoInterfaceObject]
interface NodeSelector {
Element querySelector(in DOMString selectors);
NodeList querySelectorAll(in DOMString selectors);
};
Document implements NodeSelector;
DocumentFragment implements NodeSelector;
Element implements NodeSelector;
};

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
Basic support 1 3.5 (1.9.1)bug 416317 9 8 (CSS2 selectors only) 10 3.2 (525.3)WebKit bug 16587
Feature Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support 2.1 yes 9 10.0 3.2

从接口定义可以看到Document、DocumentFragment、Element都实现了NodeSelector接口。即这三种类型的元素都拥有者两个方法。querySelector和querySelectorAll的参数须是符合 css selector 的字符串。不同的是querySelector返回的是一个对象,querySelectorAll返回的一个集合(NodeList)。

目前 IE8/9及Firefox/Chrome/Safari/Opera 的最新版已经支持它们。

如想获取页面class属性为"red"的元素,除了使用document.getElementsByClassName('red')还可以使用document.querySelector('.red')和document.querySelectorAll('.red')。

但Element.querySelector和Element.querySelectorAll的实现有错误,如下

<div id="d1"> 
<p><a href="http://www.sina.com.cn">SINA</a></p> 
</div> 
<script type="text/javascript"> 
function $(id){return document.getElementById(id);} 
var d1 = $('d1'); 
var obj1 = d1.querySelector('div a'); 
var obj2 = d1.querySelectorAll('div a'); 
alert(obj1); // -> http://www.sina.com.cn/ 
alert(obj2.length); // -> 1 
</script>

如果支持这两个方法的浏览器可以看到分别弹出了“http://www.sina.com.cn/”,和 “1”。说明查询到了想要的元素或元素集合。这与W3C的定义却是不合的,根据定义应该是在元素d1范围内查找"div a",而d1内压根没有div。因此应该分别返回null,空集合。

jQuery1.4.2 及之前版本中只使用了document.querySelectorAll,没有使用Element.querySelectorAll。 jQuery1.4.3 后使用了Element.querySelectorAll,但做了修复。在选择器前加了"#__sizzle__"以强制其在指定元素内查找(3903-3918行)。简化下

function $(id){return document.getElementById(id);} 
var d1 = $('d1'); 
var obj1 = d1.querySelector('div a'); 
var obj2 = d1.querySelectorAll('div a'); 
var old = d1.id, id = d1.id = "__sizzle__"; 
try { 
var query = '#' + id + ' div a'; 
alert(d1.querySelector( query )); 
alert(d1.querySelectorAll( query ).length); 
} catch(e) { 
} finally { 
old ? d1.id = old : d1.removeAttribute( "id" ); 
}

实现很巧妙,指定范围的元素如果有id,将其保留在old,"__sizzle__"赋值其作为临时id,在选择器"div a"前指定查找范围为"#__sizzle__",即d1。finally语句来最后清理,如果指定范围的元素本身有id将其恢复为old,没有则去掉临时的id属性"__sizzle__"。

相关:
http://msdn.microsoft.com/en-us/library/cc288169%28v=VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/cc304115%28VS.85%29.aspx
https://developer.mozilla.org/En/DOM/Document.querySelector
https://developer.mozilla.org/En/DOM/Document.querySelectorAll
https://developer.mozilla.org/En/DOM/element.querySelector
https://developer.mozilla.org/En/DOM/Element.querySelectorAll

Javascript 相关文章推荐
juqery 学习之三 选择器 可见性 元素属性
Nov 25 Javascript
jquery实现带复选框的表格行选中删除时高亮显示
Aug 01 Javascript
JavaScript中使用ActiveXObject操作本地文件夹的方法
Mar 28 Javascript
javascript基本算法汇总
Mar 09 Javascript
JavaScript中子对象访问父对象的方式详解
Sep 01 Javascript
详解JavaScript中js对象与JSON格式字符串的相互转换
Feb 14 Javascript
深入解析Vue 组件命名那些事
Jul 18 Javascript
详解vue表单——小白速看
Apr 08 Javascript
Webpack的dll功能使用
Jun 28 Javascript
Vue全局分页组件的实现代码
Aug 10 Javascript
微信小程序Page中data数据操作和函数调用方法
May 08 Javascript
Vue 中可以定义组件模版的几种方式
Aug 06 Javascript
jQuery-onload让第一次页面加载时图片是淡入方式显示
May 23 #Javascript
jquery.pagination.js 无刷新分页实现步骤分享
May 23 #Javascript
jquery.Jwin.js 基于jquery的弹出层插件代码
May 23 #Javascript
使用JQuery和CSS模拟超链接的用户单击事件的实现代码
May 23 #Javascript
基于jquery tab切换(防止页面刷新)
May 23 #Javascript
jQuery下通过replace字符串替换实现大小图片切换
May 22 #Javascript
js面向对象 多种创建对象方法小结
May 21 #Javascript
You might like
遍历指定目录下的所有目录和文件的php代码
2011/11/27 PHP
phpMyAdmin出现无法载入 mcrypt 扩展,请检查PHP配置的解决方法
2012/03/26 PHP
浅谈apache和nginx的rewrite的区别
2013/02/22 PHP
php简单开启gzip压缩方法(zlib.output_compression)
2013/04/13 PHP
PHP删除HTMl标签的三种解决方法
2013/06/30 PHP
Linux下编译redis和phpredis的方法
2016/04/07 PHP
详解Laravel视图间共享数据与视图Composer
2016/08/04 PHP
bindParam和bindValue的区别以及在Yii2中的使用详解
2018/03/12 PHP
JS setCapture 区域外事件捕捉
2010/03/18 Javascript
浅析js中的浮点型运算问题
2014/01/06 Javascript
删除节点的jquery代码
2014/01/13 Javascript
通过点击jqgrid表格弹出需要的表格数据
2015/12/02 Javascript
由简入繁实现Jquery树状结构的方法(推荐)
2016/06/10 Javascript
javascript中UMD规范的代码推演
2018/08/29 Javascript
node.js实现上传文件功能
2019/07/15 Javascript
适合前端Vue开发童鞋的跨平台Weex的使用详解
2019/10/16 Javascript
JavaScript实现鼠标经过表格某行时此行变色
2020/11/20 Javascript
Python实现国外赌场热门游戏Craps(双骰子)
2015/03/31 Python
编写Python爬虫抓取暴走漫画上gif图片的实例分享
2016/04/20 Python
Python Matplotlib库安装与基本作图示例
2019/01/09 Python
对Python3 序列解包详解
2019/02/16 Python
python3 selenium自动化测试 强大的CSS定位方法
2019/08/23 Python
浅析python 动态库m.so.1.0错误问题
2020/05/09 Python
Python Dict找出value大于某值或key大于某值的所有项方式
2020/06/05 Python
大数据分析用java还是Python
2020/07/06 Python
解决PyCharm IDE环境下,执行unittest不生成测试报告的问题
2020/09/03 Python
利用python汇总统计多张Excel
2020/09/22 Python
css3圆角样式分享自定义按钮样式
2013/12/27 HTML / CSS
html5中canvas学习笔记2-判断浏览器是否支持canvas
2013/01/06 HTML / CSS
.NET初级开发工程师面试题
2014/04/18 面试题
小组口号大全
2014/06/09 职场文书
考试作弊检讨书范文
2015/01/27 职场文书
学雷锋日活动总结
2015/02/06 职场文书
教师节主持词开场白
2015/05/29 职场文书
公司老总年会致辞
2015/07/30 职场文书
教师学习心得体会范文
2016/01/21 职场文书