各浏览器中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 相关文章推荐
鼠标滑上去后图片放大浮出效果的js代码
May 28 Javascript
js实现飞入星星特效代码
Oct 17 Javascript
DOM节点的替换或修改函数replaceChild()用法实例
Jan 12 Javascript
Jqgrid之强大的表格插件应用
Dec 02 Javascript
浅谈JS原型对象和原型链
Mar 02 Javascript
JavaScript 数组的深度复制解析
Nov 02 Javascript
微信小程序 Nginx环境配置详细介绍
Feb 14 Javascript
JavaScript订单操作小程序完整版
Jun 23 Javascript
JavaScript转换数据库DateTime字段类型方法
Jun 27 Javascript
微信小程序实现图片压缩功能
Jan 26 Javascript
Angular利用HTTP POST下载流文件的步骤记录
Jul 26 Javascript
微信小程序反编译的实现
Dec 10 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 的 __FILE__ 常量
2007/01/15 PHP
人尽可用的Windows技巧小贴士之下篇
2007/03/22 PHP
php获取是星期几的的一些常用姿势
2019/12/15 PHP
Laravel5.1框架路由分组用法实例分析
2020/01/04 PHP
jquery api参考 visualjquery 中国线路 速度快
2007/11/30 Javascript
FireFox与IE 下js兼容触发click事件的代码
2008/11/20 Javascript
JQuery实现表格中相同单元格合并示例代码
2013/06/26 Javascript
使用Node.js实现一个简单的FastCGI服务器实例
2014/06/09 Javascript
jQuery获取动态生成的元素示例
2014/06/15 Javascript
node.js中的url.format方法使用说明
2014/12/10 Javascript
在Javascript操作JSON对象,增加 删除 修改的简单实现
2016/06/02 Javascript
AngularJs页面筛选标签小功能
2016/08/01 Javascript
JS函数修改html的元素内容,及修改属性内容的方法
2016/10/28 Javascript
浅谈js继承的实现及公有、私有、静态方法的书写
2016/10/28 Javascript
解决微信内置浏览器返回上一页强制刷新问题方法
2017/02/05 Javascript
[00:57]辉夜杯战队访谈宣传片—VG
2015/12/25 DOTA
python分析nignx访问日志脚本分享
2015/02/26 Python
django批量导入xml数据
2016/10/16 Python
老生常谈进程线程协程那些事儿
2017/07/24 Python
python中返回矩阵的行列方法
2018/04/04 Python
python 实现判断ip连通性的方法总结
2018/04/22 Python
详解python3中的真值测试
2018/08/13 Python
python3.4 将16进制转成字符串的实例
2019/06/12 Python
使用Python制作表情包实现换脸功能
2019/07/19 Python
django 信号调度机制详解
2019/07/19 Python
python连接、操作mongodb数据库的方法实例详解
2019/09/11 Python
pycharm工具连接mysql数据库失败问题
2020/04/01 Python
call在Python中改进数列的实例讲解
2020/12/09 Python
销售文员岗位职责
2013/11/29 职场文书
最新奶茶店创业计划书
2014/01/25 职场文书
社区消防工作实施方案
2014/03/21 职场文书
2014年办公室文秘工作总结
2014/12/09 职场文书
多人股份制合作协议书
2016/03/19 职场文书
一文搞懂redux在react中的初步用法
2021/06/09 Javascript
Rust 连接 PostgreSQL 数据库的详细过程
2022/01/22 PostgreSQL
PHP面试题 wakeup魔法 Ezpop pop序列化与反序列化
2022/04/11 PHP