再谈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模板入门介绍
Sep 26 Javascript
如何在JavaScript中实现私有属性的写类方式(二)
Dec 04 Javascript
js处理自己不能定义二维数组的方法详解
Mar 03 Javascript
Javascript控制div属性动态变化实例分析
Oct 08 Javascript
深入浅析AngularJS中的一次性数据绑定 (bindonce)
May 11 Javascript
详解Vue微信公众号开发踩坑全记录
Aug 21 Javascript
vue项目实现记住密码到cookie功能示例(附源码)
Jan 31 Javascript
详谈vue+webpack解决css引用图片打包后找不到资源文件的问题
Mar 06 Javascript
Vue引入jquery实现平滑滚动到指定位置
May 09 jQuery
Vue实现动态添加或者删除对象和对象数组的操作方法
Sep 21 Javascript
Vue父子传递实例讲解
Feb 14 Javascript
解决vuex改变了state的值,但是页面没有更新的问题
Nov 12 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下把数组保存为文件格式的实例应用
2010/02/08 PHP
PHP 创建标签云函数代码
2010/05/26 PHP
PHP中exec函数和shell_exec函数的区别
2014/08/20 PHP
php中实现用数组妩媚地生成要执行的sql语句
2015/07/10 PHP
PHP解压ZIP文件到指定文件夹的方法
2016/11/17 PHP
基于jquery的兼容各种浏览器的iframe自适应高度的脚本
2010/08/13 Javascript
推荐17个优美新鲜的jQuery的工具提示插件
2012/09/14 Javascript
JS子父窗口互相操作取值赋值的方法介绍
2013/05/11 Javascript
JS动态添加Table的TR,TD实现方法
2015/01/28 Javascript
jquery+正则实现统一的表单验证
2015/09/20 Javascript
JS区分浏览器页面是刷新还是关闭
2016/04/17 Javascript
jQuery之简单的表单验证实例
2016/07/07 Javascript
JS组件系列之使用HTML标签的data属性初始化JS组件
2016/09/14 Javascript
利用Js的console对象,在控制台打印调式信息测试Js的实现
2016/11/26 Javascript
Node.js 利用cheerio制作简单的网页爬虫示例
2018/03/01 Javascript
vueScroll实现移动端下拉刷新、上拉加载
2019/03/22 Javascript
微信小程序用户授权弹窗 拒绝时引导用户重新授权实现
2019/07/29 Javascript
py2exe 编译ico图标的代码
2013/03/08 Python
Python网站验证码识别
2016/01/25 Python
Python标准库之itertools库的使用方法
2017/09/07 Python
对Python 数组的切片操作详解
2018/07/02 Python
解决Pycharm调用Turtle时 窗口一闪而过的问题
2019/02/16 Python
pandas 选取行和列数据的方法详解
2019/08/08 Python
Python 实现的 Google 批量翻译功能
2019/08/26 Python
python脚本第一行如何写
2020/08/30 Python
Django实现文章详情页面跳转代码实例
2020/09/16 Python
详解Sticky Footer 绝对底部的两种套路
2017/11/03 HTML / CSS
师范大学应届生求职信
2013/11/21 职场文书
日语专业个人求职信范文
2014/02/02 职场文书
家长对老师的感言
2014/03/11 职场文书
打造高效课堂实施方案
2014/03/22 职场文书
教师批评与自我批评心得体会
2014/10/16 职场文书
2015年人事科工作总结
2015/04/28 职场文书
2015暑期社会实践调查报告
2015/07/14 职场文书
MySQL 可扩展设计的基本原则
2021/05/14 MySQL
2022微信温控新功能上线
2022/05/09 数码科技