再谈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 08 Javascript
JQuery 遮罩层实现(mask)实现代码
Jan 09 Javascript
JQuery从头学起第二讲
Jul 04 Javascript
jQuery源码分析-03构造jQuery对象-工具函数
Nov 14 Javascript
javascript实现网页端解压并查看zip文件
Dec 15 Javascript
javascript 中的事件委托详解
Oct 25 Javascript
解析Json字符串的三种方法日常常用
May 02 Javascript
JS使用遮罩实现点击某区域以外时弹窗的弹出与关闭功能示例
Jul 31 Javascript
基于Webpack4和React hooks搭建项目的方法
Feb 05 Javascript
详解JavaScript原生封装ajax请求和Jquery中的ajax请求
Feb 14 jQuery
微信小程序新手教程之启动页的重要性
Mar 03 Javascript
js+canvas实现纸牌游戏
Mar 16 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 数据库树的遍历方法
2009/02/06 PHP
Nginx服务器上安装并配置PHPMyAdmin的教程
2015/08/18 PHP
php中实现进程锁与多进程的方法
2016/09/18 PHP
Laravel如何自定义command命令浅析
2019/03/23 PHP
JS实多级联动下拉菜单类,简单实现省市区联动菜单!
2007/05/03 Javascript
利用jquery.qrcode在页面上生成二维码且支持中文
2014/02/12 Javascript
详解JavaScript基于面向对象之继承实例
2015/12/16 Javascript
WebGL利用FBO完成立方体贴图效果完整实例(附demo源码下载)
2016/01/26 Javascript
JavaScript导航脚本判断当前导航
2016/07/12 Javascript
jQuery增加、删除及修改select option的方法
2016/08/19 Javascript
简单谈谈JS数组中的indexOf方法
2016/10/13 Javascript
javascript 判断一个对象为数组的方法
2017/05/03 Javascript
解决VUEX刷新的时候出现数据消失
2017/07/03 Javascript
关于在mongoose中填充外键的方法详解
2017/08/14 Javascript
ztree实现左边动态生成树右边为内容详情功能
2017/11/03 Javascript
angularjs数组判断是否含有某个元素的实例
2018/02/27 Javascript
JavaScript中变量、指针和引用功能与操作示例
2018/08/04 Javascript
Vue常见面试题整理【值得收藏】
2018/09/20 Javascript
如何用Node写页面爬虫的工具集
2018/10/26 Javascript
最简单的JS实现json转csv的方法
2019/01/10 Javascript
jQuery与原生JavaScript选择HTML元素集合用法对比分析
2019/11/26 jQuery
VUE 动态组件的应用案例分析
2019/12/02 Javascript
浅谈Python实现2种文件复制的方法
2018/01/19 Python
python程序实现BTC(比特币)挖矿的完整代码
2021/01/20 Python
小程序canvas中文字设置居中锚点
2019/04/16 HTML / CSS
Volcom法国官网:美国冲浪滑板品牌
2017/05/25 全球购物
亚洲最大的眼镜批发商和零售商之一:Glasseslit
2018/10/08 全球购物
美国室内和室外装饰花盆购物网站:ePlanters
2019/03/22 全球购物
网上常见的一份Linux面试题(多项选择部分)
2014/09/09 面试题
电子商务应届生求职信
2013/11/16 职场文书
大学生社会实践自我鉴定
2014/03/24 职场文书
物业公司的岗位任命书
2014/06/06 职场文书
校园绿化美化方案
2014/06/08 职场文书
党章培训心得体会
2014/09/04 职场文书
幼儿园中班教学反思
2016/03/03 职场文书
HTML页面点击按钮关闭页面的多种方式
2022/12/24 HTML / CSS