再谈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 利用Image对象实现的埋点(某处的点击数)统计
Dec 28 Javascript
IE6-8中Date不支持toISOString的修复方法
May 04 Javascript
将HTML格式的String转化为HTMLElement的实现方法
Aug 07 Javascript
Node.js Addons翻译(C/C++扩展)
Jun 12 Javascript
关于Vue.js一些问题和思考学习笔记(1)
Dec 02 Javascript
关于Stream和Buffer的相互转换详解
Jul 26 Javascript
React学习之事件绑定的几种方法对比
Sep 24 Javascript
vue2实现可复用的轮播图carousel组件详解
Nov 27 Javascript
详解Vue改变数组中对象的属性不重新渲染View的解决方案
Sep 21 Javascript
如何在微信小程序中实现Mixins方案
Jun 20 Javascript
JavaScript监听一个DOM元素大小变化
Apr 26 Javascript
JS如何生成动态列表
Sep 22 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
destoon常用的安全设置概述
2014/06/21 PHP
PHP管理依赖(dependency)关系工具 Composer的自动加载(autoload)
2014/08/18 PHP
php专用数组排序类ArraySortUtil用法实例
2015/04/03 PHP
php隐藏实际地址的文件下载方法
2015/04/18 PHP
通过PHP简单实例介绍文件上传
2015/12/16 PHP
laravel实现按月或天或小时统计mysql数据的方法
2019/10/09 PHP
离开页面时检测表单元素是否被修改,提示保存的js代码
2010/08/25 Javascript
jquery仿京东导航/仿淘宝商城左侧分类导航下拉菜单效果
2013/04/24 Javascript
javascript字符串函数汇总
2015/12/06 Javascript
JavaScript提高性能知识点汇总
2016/01/15 Javascript
jQuery下拉菜单的实现代码
2016/11/03 Javascript
js前端日历控件(悬浮、拖拽、自由变形)
2017/03/02 Javascript
Vue非父子组件通信详解
2017/06/12 Javascript
Vue2.0 实现单选互斥的方法
2018/04/13 Javascript
微信小程序授权登录解决方案的代码实例(含未通过授权解决方案)
2019/05/10 Javascript
详解js location.href和window.open的几种用法和区别
2019/12/02 Javascript
Win7上搭建Cocos2d-x 3.1.1开发环境
2014/07/03 Python
Eclipse和PyDev搭建完美Python开发环境教程(Windows篇)
2016/11/16 Python
使用Django搭建web服务器的例子(最最正确的方式)
2019/08/29 Python
Python发送邮件的实例代码讲解
2019/10/16 Python
使用python+poco+夜神模拟器进行自动化测试实例
2020/04/23 Python
通过实例简单了解python yield使用方法
2020/08/06 Python
python mongo 向数据中的数组类型新增数据操作
2020/12/05 Python
CSS3中box-shadow的用法介绍
2015/07/15 HTML / CSS
html5 的a标签 Href 拨电话的写法
2013/11/04 HTML / CSS
canvas裁剪clip()函数的具体使用
2018/03/01 HTML / CSS
在线服装零售商:SheIn
2016/07/22 全球购物
linux面试题参考答案(1)
2016/01/22 面试题
《跟踪台风的卫星》教学反思
2014/04/10 职场文书
电影雷锋观后感
2015/06/10 职场文书
《七律·长征》教学反思
2016/02/16 职场文书
深度好文:50条没人告诉你的人生经验,句句精辟
2019/08/22 职场文书
MySQL表的增删改查基础教程
2021/04/07 MySQL
Python趣味挑战之实现简易版音乐播放器
2021/05/28 Python
Golang入门之计时器
2022/05/04 Golang
Java中的Kotlin 内部类原理
2022/06/16 Java/Android