各浏览器中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中void(0)的具体含义解释
Feb 27 Javascript
巧用js提交表单轻松解决一个页面有多个提交按钮
Nov 17 Javascript
js+html5实现可在手机上玩的拼图游戏
Jul 17 Javascript
JS组件系列之Bootstrap table表格组件神器【终结篇】
May 10 Javascript
JavaScript获取IP获取的是IPV6 如何校验
Jun 12 Javascript
js 弹出对话框(遮罩)透明,可拖动的简单实例
Jul 11 Javascript
js 基础篇必看(点击事件轮播图的简单实现)
Aug 20 Javascript
Javascript中常用类型的格式化方法小结
Dec 26 Javascript
利用SpringMVC过滤器解决vue跨域请求的问题
Feb 10 Javascript
jQuery实现导航样式布局操作示例【可自定义样式布局】
Jul 24 jQuery
利用js将ajax获取到的后台数据动态加载至网页中的方法
Aug 08 Javascript
如何用原生js写一个弹窗消息提醒插件
May 24 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
探讨:如何使用PhpDocumentor生成文档
2013/06/25 PHP
PHP关于IE下的iframe跨域导致session丢失问题解决方法
2013/10/10 PHP
PHP环境搭建(php+Apache+mysql)
2016/11/14 PHP
php 广告点击统计代码(php+mysql)
2018/02/21 PHP
浅析JS刷新框架中的其他页面 &amp;&amp; JS刷新窗口方法汇总
2013/07/08 Javascript
jQuery中RadioButtonList的功能及用法实例介绍
2013/08/23 Javascript
jQuery学习笔记之总体架构
2014/06/03 Javascript
JavaScript中的toDateString()方法使用详解
2015/06/12 Javascript
JS常见问题之为什么点击弹出的i总是最后一个
2016/01/05 Javascript
JavaScript编写点击查看大图的页面半透明遮罩层效果实例
2016/05/09 Javascript
jQuery EasyUI常用数据验证汇总
2016/09/18 Javascript
Angular4学习笔记之新建项目的方法
2017/07/18 Javascript
NodeJS收发GET和POST请求的示例代码
2017/08/25 NodeJs
原生JS封装_new函数实现new关键字的功能
2018/08/12 Javascript
jsonp跨域及实现百度首页联想功能的方法
2018/08/30 Javascript
vue interceptor 使用教程实例详解
2018/09/13 Javascript
webpack4.0+vue2.0利用批处理生成前端单页或多页应用的方法
2019/06/28 Javascript
js 获取本周、上周、本月、上月、本季度、上季度的开始结束日期
2020/02/01 Javascript
微信小程序整个页面的自动适应布局的实现
2020/07/12 Javascript
Vue组件跨层级获取组件操作
2020/07/27 Javascript
python33 urllib2使用方法细节讲解
2013/12/03 Python
使用Python脚本来获取Cisco设备信息的示例
2015/05/04 Python
pandas实现选取特定索引的行
2018/04/20 Python
Django实现跨域的2种方法
2019/07/31 Python
python使用docx模块读写docx文件的方法与docx模块常用方法详解
2020/02/17 Python
细数nn.BCELoss与nn.CrossEntropyLoss的区别
2020/02/29 Python
python爬虫容易学吗
2020/06/02 Python
Python根据URL地址下载文件并保存至对应目录的实现
2020/11/15 Python
纯CSS打造(无图像无js)的非常流行的讲话(语音)气泡效果
2012/12/28 HTML / CSS
Homestay中文官网:全球寄宿家庭
2018/10/18 全球购物
法国足球商店:Footcenter
2019/07/06 全球购物
影视制作岗位职责
2013/12/04 职场文书
空中乘务员岗位职责
2014/03/08 职场文书
服务标语口号
2014/07/01 职场文书
个人先进材料范文
2014/12/30 职场文书
初中班主任培训心得体会
2016/01/07 职场文书