再谈querySelector和querySelectorAll的区别与联系


Posted in Javascript onApril 20, 2012

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

使用方法:

var element = baseElement.querySelector(selectors); 
var elementList = baseElement.querySelectorAll(selectors);

这在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" ),<BR> nid = old || id, 
try { 
if ( !relativeHierarchySelector || hasParent ) { 
return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); 
} 
} catch(pseudoError) {} <BR>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;

非常感谢大牛JK的回复,提供了另外一种方法。

Javascript 相关文章推荐
如何使用Javascript正则表达式来格式化XML内容
Jul 04 Javascript
document.addEventListener使用介绍
Mar 07 Javascript
jquery attr方法获取input的checked属性问题
May 26 Javascript
javascript获取select值的方法分析
Jul 02 Javascript
JS组件Bootstrap Select2使用方法详解
Apr 17 Javascript
深入理解jQuery中的事件冒泡
May 24 Javascript
详解XMLHttpRequest(二)响应属性、二进制数据、监测上传下载进度
Sep 14 Javascript
AngularJS创建自定义指令的方法详解
Nov 03 Javascript
简单谈谈ES6的六个小特性
Nov 18 Javascript
jQuery代码实现实时获取时间
Jan 29 Javascript
vue pages 多入口项目 + chainWebpack 全局引用缩写说明
Sep 21 Javascript
javascript遍历对象的五种方式实例代码
Oct 24 Javascript
js querySelector和getElementById通过id获取元素的区别
Apr 20 #Javascript
仿微博字符限制效果实现代码
Apr 20 #Javascript
javascript 另一种图片滚动切换效果思路
Apr 20 #Javascript
分享一个自定义的console类 让你不再纠结JS中的调试代码的兼容
Apr 20 #Javascript
浏览器解析js生成的html出现样式问题的解决方法
Apr 16 #Javascript
基于jquery的不规则矩形的排列实现代码
Apr 16 #Javascript
JavaScript打开word文档的实现代码(c#)
Apr 16 #Javascript
You might like
Js实现手机发送验证码时按钮延迟操作
2014/06/20 Javascript
jquery获取checkbox的值并post提交
2015/01/14 Javascript
JavaScript人脸识别技术及脸部识别JavaScript类库Tracking.js
2015/09/14 Javascript
jquery实现简易的移动端验证表单
2015/11/08 Javascript
Bootstrap的Refresh Icon也spin起来
2016/07/13 Javascript
浅谈JS之tagNaem和nodeName
2016/09/13 Javascript
Angular.Js的自动化测试详解
2016/12/09 Javascript
Angular directive递归实现目录树结构代码实例
2017/05/05 Javascript
js+html5实现页面可刷新的倒计时效果
2017/07/15 Javascript
jQuery轮播图实例详解
2018/08/15 jQuery
解决Js先触发失去焦点事件再执行点击事件的问题
2018/08/30 Javascript
jQuery+PHP实现上传裁剪图片
2020/06/29 jQuery
小程序简单两栏瀑布流效果的实现
2019/12/18 Javascript
vue使用nprogress加载路由进度条的方法
2020/06/04 Javascript
vue实现桌面向网页拖动文件的示例代码(可显示图片/音频/视频)
2021/03/01 Vue.js
Python Web框架Flask中使用百度云存储BCS实例
2015/02/08 Python
Python格式化压缩后的JS文件的方法
2015/03/05 Python
python爬虫之BeautifulSoup 使用select方法详解
2017/10/23 Python
简述Python2与Python3的不同点
2018/01/21 Python
Windows下python3.7安装教程
2018/07/31 Python
用python生成(动态彩色)二维码的方法(使用myqr库实现)
2019/06/24 Python
python使用装饰器作日志处理的方法
2019/07/11 Python
python list多级排序知识点总结
2019/10/23 Python
利用Python绘制Jazz网络图的例子
2019/11/21 Python
python 使用cx-freeze打包程序的实现
2020/03/14 Python
浅谈python 中的 type(), dtype(), astype()的区别
2020/04/09 Python
Django 解决新建表删除后无法重新创建等问题
2020/05/21 Python
python 在sql语句中使用%s,%d,%f说明
2020/06/06 Python
Python3交互式shell ipython3安装及使用详解
2020/07/11 Python
css3 响应式媒体查询的示例代码
2019/09/25 HTML / CSS
如何做好总经理助理
2013/11/12 职场文书
网络维护中文求职信
2014/01/03 职场文书
理想点亮人生演讲稿
2014/05/21 职场文书
幼儿园重阳节活动总结
2015/05/05 职场文书
Python网络编程之ZeroMQ知识总结
2021/04/25 Python
Android开发之WECHAT微信小程序路由跳转的两种形式
2022/04/12 Java/Android