再谈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 Firefox3.5中操作select的问题
Jul 10 Javascript
简略的前端架构心得&amp;&amp;基于editor为例子的编码小技巧
Nov 25 Javascript
对table和ul实现js分页示例分享
Feb 24 Javascript
获取当前按钮或者html的ID名称实例(推荐)
Jun 23 Javascript
详解webpack 多页面/入口支持&amp;公共组件单独打包
Jun 29 Javascript
Bootstrap一款超好用的前端框架
Sep 25 Javascript
微信小程序picker组件简单用法示例【附demo源码下载】
Dec 05 Javascript
vue实现nav导航栏的方法
Dec 13 Javascript
three.js实现3D影院的原理的代码分析
Dec 18 Javascript
node.js域名解析实现方法详解
Nov 05 Javascript
ant design实现圈选功能
Dec 17 Javascript
JavaScript之scrollTop、scrollHeight、offsetTop、offsetHeight等属性学习笔记
Jul 15 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
mysql中存储过程、函数的一些问题
2007/02/14 PHP
ThinkPHP中url隐藏入口文件后接收alipay传值的方法
2014/12/09 PHP
php中动态调用函数的方法
2015/03/16 PHP
PHP基于PDO实现的SQLite操作类【包含增删改查及事务等操作】
2017/06/21 PHP
CentOS7系统搭建LAMP及更新PHP版本操作详解
2020/03/26 PHP
JS实现将人民币金额转换为大写的示例代码
2014/02/13 Javascript
Node.js文件操作详解
2014/08/16 Javascript
Bootstrap框架动态生成Web页面文章内目录的方法
2016/05/12 Javascript
getElementById().innerHTML与getElementById().value的区别
2016/10/27 Javascript
浅析从vue源码看观察者模式
2018/01/29 Javascript
JavaScript设计模式之调停者模式实例详解
2018/02/03 Javascript
vue实现点击当前标签高亮效果【推荐】
2018/06/22 Javascript
vue3.0中的双向数据绑定方法及优缺点
2019/08/01 Javascript
微信小程序全局变量GLOBALDATA的定义和调用过程解析
2019/09/23 Javascript
Vue退出登录时清空缓存的实现
2019/11/12 Javascript
jQuery实现小火箭返回顶部特效
2020/02/03 jQuery
JavaScript实现字符串与HTML格式相互转换
2020/03/17 Javascript
JS实现移动端可折叠导航菜单(现代都市风)
2020/07/07 Javascript
详解Django通用视图中的函数包装
2015/07/21 Python
Python自动发邮件脚本
2017/03/31 Python
python 3.6 tkinter+urllib+json实现火车车次信息查询功能
2017/12/20 Python
在PyCharm中实现关闭一个死循环程序的方法
2018/11/29 Python
意大利比基尼品牌:MISS BIKINI
2019/11/02 全球购物
新学期开学寄语
2014/01/18 职场文书
九年级历史教学反思
2014/01/27 职场文书
让生命充满爱演讲稿
2014/05/10 职场文书
文明演讲稿范文
2014/05/12 职场文书
学习之星事迹材料
2014/05/17 职场文书
社会稳定风险评估方案
2014/06/02 职场文书
爱护公物标语
2014/06/24 职场文书
公司委托书格式范文
2014/10/09 职场文书
保研推荐信格式
2015/03/25 职场文书
2015财务年度工作总结范文
2015/05/04 职场文书
表扬稿表扬信的格式及范文
2019/06/24 职场文书
深入理解python多线程编程
2021/04/18 Python
python和Appium的移动端多设备自动化测试框架
2022/04/26 Python