再谈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 验证上传图片大小[客户端]
Aug 01 Javascript
jquery里的正则表达式说明
Aug 03 Javascript
JQuery显示、隐藏div的几种方法简明总结
Apr 16 Javascript
基于jQuery实现的扇形定时器附源码下载
Oct 20 Javascript
jQuery height()、innerHeight()、outerHeight()函数的区别详解
May 23 Javascript
jQuery插件扩展测试实例
Jun 21 Javascript
JavaScript设计模式之单体模式全面解析
Sep 09 Javascript
基于EasyUI的基础之上实现树形功能菜单
Jun 28 Javascript
JavaScript之underscore_动力节点Java学院整理
Jul 03 Javascript
JavaScript解析JSON数据示例
Jul 16 Javascript
node爬取新型冠状病毒的疫情实时动态
Feb 06 Javascript
vue+element-ui JYAdmin后台管理系统模板解析
Jul 28 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
我的论坛源代码(八)
2006/10/09 PHP
PHPCMS V9 添加二级导航的思路详解
2016/10/20 PHP
php使用PDO事务配合表格读取大量数据插入操作实现方法
2017/02/16 PHP
JavaScript 常用函数库详解
2009/10/21 Javascript
基于JQuery的一句话搞定手风琴菜单
2012/09/14 Javascript
javascript制作坦克大战全纪录(2)
2014/11/27 Javascript
js实现单击图片放大图片的方法
2015/02/17 Javascript
JSONP之我见
2015/03/24 Javascript
js简单实现表单中点击按钮动态增加输入框数量的方法
2015/08/18 Javascript
clipboard.js无需Flash无需依赖任何JS库实现文本复制与剪切
2015/10/10 Javascript
jquery动画效果学习笔记(8种效果)
2015/11/13 Javascript
jQuery中常用动画效果函数(日常整理)
2016/09/17 Javascript
JavaScript实现换肤功能
2017/09/15 Javascript
微信小程序实现选项卡效果
2018/11/06 Javascript
VUE+Element环境搭建与安装的方法步骤
2019/01/24 Javascript
Vue插槽原理与用法详解
2019/03/05 Javascript
深入了解Hybrid App技术的相关知识
2019/07/17 Javascript
Vue防止白屏添加首屏动画的实例
2019/10/31 Javascript
基于JavaScript或jQuery实现网站夜间/高亮模式
2020/05/30 jQuery
[02:51]DOTA2 2015国际邀请赛中国区预选赛第一日战报
2015/05/27 DOTA
浅析Python的Django框架中的Memcached
2015/07/23 Python
python实现简单遗传算法
2018/03/19 Python
python实现汽车管理系统
2018/11/30 Python
python3 http提交json参数并获取返回值的方法
2018/12/19 Python
PyQt QListWidget修改列表项item的行高方法
2019/06/20 Python
Laravel框架表单验证格式化输出的方法
2019/09/25 Python
python计算n的阶乘的方法代码
2019/10/25 Python
Python django框架 web端视频加密的实例详解
2020/11/20 Python
新护士岗前培训制度
2014/02/02 职场文书
调查研究项目计划书
2014/04/29 职场文书
党的群众路线教育实践活动心得体会(乡镇)
2014/11/03 职场文书
侵犯商业秘密的律师函
2015/05/27 职场文书
导游词之江南园林狮子林
2019/09/16 职场文书
导游词之山西-五老峰
2019/10/07 职场文书
golang协程池模拟实现群发邮件功能
2021/05/02 Golang
Android移动应用开发指南之六种布局详解
2022/09/23 Java/Android