再谈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 相关文章推荐
让innerHTML的脚本也可以运行起来
Jul 01 Javascript
Javascript-Mozilla和IE中的一个函数直接量的问题
Jan 09 Javascript
js原生态函数中使用jQuery中的 $(this)无效的解决方法
May 25 Javascript
SyntaxHighlighter语法高亮插件使用说明
Aug 14 Javascript
jQuery中对节点进行操作的相关介绍
Apr 16 Javascript
jQuery中json对象的复制方式介绍(数组及对象)
Jun 08 Javascript
javascript判断图片是否加载完成的方法推荐
May 13 Javascript
JS全局变量和局部变量最新解析
Jun 24 Javascript
基于Angular.js实现的触摸滑动动画实例代码
Feb 19 Javascript
基于node+vue实现简单的WebSocket聊天功能
Feb 01 Javascript
vue+element-ui表格封装tag标签使用插槽
Jun 18 Javascript
通过vue.extend实现消息提示弹框的方法记录
Jan 07 Vue.js
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动态图像的创建
2006/10/09 PHP
php数据库配置文件一般做法分享
2012/07/07 PHP
PHP 闭包详解及实例代码
2016/09/28 PHP
基于JQuery的Select选择框的华丽变身
2011/08/23 Javascript
Jquery Ajax方法传值到action的方法
2014/05/11 Javascript
Javascript编写2048小游戏
2015/07/07 Javascript
jQuery实现批量判断表单中文本框非空的方法(2种方法)
2015/12/09 Javascript
Bootstrap中的表单验证插件bootstrapValidator使用方法整理(推荐)
2016/06/21 Javascript
js HTML5上传示例代码完整版
2016/10/10 Javascript
Bootstrap树形菜单插件TreeView.js使用方法详解
2016/11/01 Javascript
js实现文字无缝向上滚动
2017/02/16 Javascript
微信浏览器禁止页面下拉查看网址实例详解
2017/06/28 Javascript
bootstrap是什么_动力节点Java学院整理
2017/07/14 Javascript
javascript编程开发中取色器及封装$函数用法示例
2017/08/09 Javascript
详解Angular路由之路由守卫
2018/05/10 Javascript
Layui给数据表格动态添加一行并跳转到添加行所在页的方法
2018/08/20 Javascript
es6数值的扩展方法
2019/03/11 Javascript
详解关于JSON.parse()和JSON.stringify()的性能小测试
2019/03/14 Javascript
详解webpack打包vue项目之后生成的dist文件该怎么启动运行
2019/09/06 Javascript
JavaScript中while循环的基础使用教程
2020/08/11 Javascript
JavaScript实现HTML导航栏下拉菜单
2020/11/25 Javascript
JavaScript基于SVG的图片切换效果实例代码
2020/12/15 Javascript
vue 数据操作相关总结
2020/12/17 Vue.js
[01:05]DOTA2完美大师赛趣味视频之选手教你打职业
2017/11/23 DOTA
[34:10]Secret vs VG 2019国际邀请赛淘汰赛 败者组 BO3 第二场 8.24
2019/09/10 DOTA
python如何在循环引用中管理内存
2018/03/20 Python
Python制作微信好友背景墙教程(附完整代码)
2019/07/17 Python
python 两种方法删除空文件夹
2020/09/29 Python
Columbia美国官网:美国著名的户外服装品牌
2016/11/24 全球购物
工作人员思想汇报
2014/01/09 职场文书
十岁生日家长答谢词
2014/01/17 职场文书
2014年无财产无子女离婚协议书范本
2014/10/09 职场文书
鸡毛信观后感
2015/06/11 职场文书
Nginx+SpringBoot实现负载均衡的示例
2021/03/31 Servers
vue3获取当前路由地址
2022/02/18 Vue.js
Windows Server 2012 R2 磁盘分区教程
2022/04/29 Servers