再谈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 获取事件对象的注意点
Jul 29 Javascript
window.js 主要包含了页面的一些操作
Dec 23 Javascript
Jquery插件之多图片异步上传
Oct 20 Javascript
JavaScript将页面表格导出为Excel的具体实现
Dec 27 Javascript
Js Jquery创建一个弹出层可加载一个页面
May 08 Javascript
AngularJS内置指令
Feb 04 Javascript
BootStrap Table后台分页时前台删除最后一页所有数据refresh刷新后无数据问题
Dec 28 Javascript
js实现简易垂直滚动条
Feb 22 Javascript
解决vue单页路由跳转后scrollTop的问题
Sep 03 Javascript
JavaScript实现图片放大镜效果
Jun 27 Javascript
vue设置动态请求地址的例子
Nov 01 Javascript
5种方法告诉你如何使JavaScript 代码库更干净
Sep 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
当海贼王变成JOJO风
2020/03/02 日漫
解析csv数据导入mysql的方法
2013/07/01 PHP
ThinkPHP快速入门实例教程之数据分页
2014/07/01 PHP
php打造智能化的柱状图程序,用于报表等
2015/06/19 PHP
php文件读取方法实例分析
2015/06/20 PHP
实例简介PHP的一些高级面向对象编程的特性
2015/11/27 PHP
php查询操作实现投票功能
2016/05/09 PHP
Thinkphp实现站点静态化的方法详解
2017/03/21 PHP
JavaScript高级程序设计 读书笔记之八 Function类及闭包
2012/02/27 Javascript
jQuery toggle 代替方法
2016/03/22 Javascript
总结js函数相关知识点
2018/02/27 Javascript
JS中利用FileReader实现上传图片前本地预览功能
2018/03/02 Javascript
vue-router之nuxt动态路由设置的两种方法小结
2018/09/26 Javascript
了解Javascript中函数作为对象的魅力
2019/06/19 Javascript
jQuery实现全选、反选和不选功能的方法详解
2019/12/04 jQuery
JS实现网页时钟特效
2020/03/25 Javascript
vue实现选中效果
2020/10/07 Javascript
在Python中利用Pandas库处理大数据的简单介绍
2015/04/07 Python
Python实现Linux命令xxd -i功能
2016/03/06 Python
python 将数据保存为excel的xls格式(实例讲解)
2018/05/03 Python
详解python3安装pillow后报错没有pillow模块以及没有PIL模块问题解决
2019/04/17 Python
关于pytorch中网络loss传播和参数更新的理解
2019/08/20 Python
Pycharm+Python+PyQt5使用详解
2019/09/25 Python
Django重设Admin密码过程解析
2020/02/10 Python
Python3 io文本及原始流I/O工具用法详解
2020/03/23 Python
python如何爬取网页中的文字
2020/07/28 Python
HTML5中视频音频的使用详解
2017/07/07 HTML / CSS
澳大利亚礼品篮网站:Macarthur Baskets
2019/10/14 全球购物
一个大学生十年的职业规划
2014/01/17 职场文书
职业女性的职业规划
2014/03/04 职场文书
联片教研活动总结
2014/07/01 职场文书
语文课外活动总结
2014/08/27 职场文书
幼儿园六一儿童节开幕词
2016/03/04 职场文书
MySQL性能压力基准测试工具sysbench的使用简介
2021/04/21 MySQL
如何制作自己的原生JavaScript路由
2021/05/05 Javascript
angular4实现带搜索的下拉框
2022/03/25 Javascript