再谈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 相关文章推荐
jquery之Document元素选择器篇
Aug 14 Javascript
javascript 动态调整图片尺寸实现代码
Dec 28 Javascript
jquery解析JSON数据示例代码
Mar 17 Javascript
jQuery实现渐变下拉菜单的简单方法
Mar 11 Javascript
jquery ezUI 双击行记录弹窗查看明细的实现方法
Jun 01 Javascript
jQuery动态添加.active 实现导航效果代码思路详解
Aug 29 jQuery
使用vue-cli3新建一个项目并写好基本配置(推荐)
Apr 24 Javascript
node.js中Buffer缓冲器的原理与使用方法分析
Nov 23 Javascript
前端开发之便利店收银系统代码
Dec 27 Javascript
JavaScript仿京东秒杀倒计时
Mar 17 Javascript
js实现简单的贪吃蛇游戏
Apr 23 Javascript
原生JS实现记忆翻牌游戏
Jul 31 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
php 中的4种标记风格介绍
2012/05/10 PHP
浏览器预览PHP文件时顶部出现空白影响布局分析原因及解决办法
2013/01/11 PHP
php 中的closure用法详解
2017/06/12 PHP
php微信公众号开发之微信企业付款给个人
2018/10/04 PHP
PHP基于面向对象封装的分页类示例
2019/03/15 PHP
PHP实现给定一列字符,生成指定长度的所有可能组合示例
2019/06/22 PHP
php 利用socket发送GET,POST请求的实例代码
2020/07/04 PHP
JavaScript 学习初步 入门教程
2010/03/25 Javascript
jQuery1.4.2与老版本json格式兼容的解决方法
2011/02/12 Javascript
JS Pro-深入面向对象的程序设计之继承的详解
2013/05/07 Javascript
使用Math.floor与Math.random取随机整数的方法详解
2013/05/07 Javascript
JavaScript中判断整字类型最简洁的实现方法
2014/11/08 Javascript
jQuery前端分页示例分享
2015/02/10 Javascript
基于BootStrap实现局部刷新分页实例代码
2016/08/08 Javascript
懒加载实现的分页&amp;&amp;网站footer自适应
2016/12/21 Javascript
NodeJS仿WebApi路由示例
2017/02/28 NodeJs
node简单实现一个更改头像功能的示例
2017/12/29 Javascript
VUE+Element环境搭建与安装的方法步骤
2019/01/24 Javascript
JavaScript 监听组合按键思路及代码实现
2020/07/28 Javascript
[57:22]2018DOTA2亚洲邀请赛 4.7总决赛 LGD vs Mineski 第五场
2018/04/10 DOTA
Python实现全角半角字符互转的方法
2016/11/28 Python
Python机器学习库scikit-learn安装与基本使用教程
2018/06/25 Python
如何在django里上传csv文件并进行入库处理的方法
2019/01/02 Python
在python中修改.properties文件的操作
2020/04/08 Python
Python 数据的累加与统计的示例代码
2020/08/03 Python
h5移动端调用支付宝、微信支付的实现
2020/06/08 HTML / CSS
美国最好的保健品打折网店:Swanson
2017/08/04 全球购物
硕士毕业论文导师评语
2014/12/31 职场文书
会计专业自荐信范文
2015/03/05 职场文书
房地产财务经理岗位职责
2015/04/08 职场文书
工厂仓库管理员岗位职责
2015/04/09 职场文书
2015年学校党建工作总结
2015/05/19 职场文书
小学运动会入场词
2015/07/18 职场文书
2016猴年春节问候语
2015/11/11 职场文书
nginx 反向代理之 proxy_pass的实现
2021/03/31 Servers
mysql数据库入门第一步之创建表
2021/05/14 MySQL