各浏览器中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 相关文章推荐
Javascript合并表格中具有相同内容单元格示例
Aug 11 Javascript
实现51Map地图接口(示例代码)
Nov 22 Javascript
React.js入门学习第一篇
Mar 30 Javascript
jquery跟随屏幕滚动效果的实现代码
Apr 13 Javascript
JS控制页面跳转时未请求要跳转的地址怎么回事
Oct 14 Javascript
JavaScript 控制字体大小设置的方法
Nov 23 Javascript
JavaScript给每一个li节点绑定点击事件的实现方法
Dec 01 Javascript
简单理解js的冒泡排序
Dec 19 Javascript
解决option标签selected=&quot;selected&quot;属性失效的问题
Nov 06 Javascript
在Chrome DevTools中调试JavaScript的实现
Apr 07 Javascript
小程序中的箭头函数的具体使用
Jun 19 Javascript
JavaScript arguments.callee作用及替换方案详解
Sep 02 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 七大优势分析
2009/06/23 PHP
基于PHP输出缓存(output_buffering)的深入理解
2013/06/13 PHP
ThinkPHP框架实现导出excel数据的方法示例【基于PHPExcel】
2018/05/12 PHP
PHP常用字符串函数小结(推荐)
2018/08/05 PHP
PHP使用函数用法详解
2018/09/30 PHP
PHP远程连接oracle数据库操作实现方法图文详解
2019/04/11 PHP
键盘控制事件应用教程大全
2006/11/24 Javascript
HTML中Select不用Disabled实现ReadOnly的效果
2008/04/07 Javascript
js添加select下默认的option的value和text的方法
2014/10/19 Javascript
很不错的两款Bootstrap Icon图标选择组件
2016/01/28 Javascript
jQuery validate+artdialog+jquery form实现弹出表单思路详解
2016/04/18 Javascript
jQuery对象的链式操作用法分析
2016/05/10 Javascript
vue实现移动端图片裁剪上传功能
2020/08/18 Javascript
修改UA在PC中访问只能在微信中打开的链接方法
2017/11/27 Javascript
nodejs之koa2请求示例(GET,POST)
2018/08/07 NodeJs
Vue实现简单分页器
2018/12/29 Javascript
vue+elementUI 复杂表单的验证、数据提交方案问题
2019/06/24 Javascript
Vue中的transition封装组件的实现方法
2019/08/13 Javascript
Python实用日期时间处理方法汇总
2015/05/09 Python
详解python之多进程和进程池(Processing库)
2017/06/09 Python
Python enumerate索引迭代代码解析
2018/01/19 Python
用TensorFlow实现多类支持向量机的示例代码
2018/04/28 Python
python3通过selenium爬虫获取到dj商品的实例代码
2019/04/25 Python
python 并发下载器实现方法示例
2019/11/22 Python
Python 使用 environs 库定义环境变量的方法
2020/02/25 Python
python GUI库图形界面开发之PyQt5树形结构控件QTreeWidget详细使用方法与实例
2020/03/02 Python
pycharm设置默认的UTF-8编码模式的方法详解
2020/06/01 Python
健康监测猫砂:Pretty Litter
2017/05/25 全球购物
介绍一下OSI七层模型
2012/07/03 面试题
Linux如何压缩可执行文件
2014/03/27 面试题
英语文学专业学生的自我评价
2013/10/31 职场文书
会计专业的自荐信
2013/12/12 职场文书
2014年辅导员工作总结
2014/11/18 职场文书
交通事故和解协议书
2015/01/27 职场文书
离婚协议书范文2016
2016/03/18 职场文书
详解vue中v-for的key唯一性
2021/05/15 Vue.js