querySelector和querySelectorAll是W3C提供的新的查询接口
目前 IE8/9及Firefox/Chrome/Safari/Opera 的最新版已经支持它们。
但是Element.querySelectorAll有个bug
<div>
<div id="bar"> <span> <a href="###">asfd</a> </span> </div>
</div>
var bar = document.getElementById('bar'); console.log(bar.querySelectorAll('div span a').length); // 1 console.log(bar.querySelectorAll('span a').length); // 1 console.log($('div span a',bar)); // jQuery没有选择到
div span a 这里本该选择不到的,结果却选择到了
下面是ExtJS的兼容实现:
try { /* * This checking here is to "fix" the behaviour of querySelectorAll * for non root document queries. The way qsa works is intentional, * however it's definitely not the expected way it should work. * When descendant selectors are used, only the lowest selector must be inside the root! * More info: http://ejohn.org/blog/thoughts-on-queryselectorall/ * So we create a descendant selector by prepending the root's ID, and query the parent node. * UNLESS the root has no parent in which qsa will work perfectly. * * We only modify the path for single selectors (ie, no multiples), * without a full parser it makes it difficult to do this correctly. */
// startIdRe = /^\s*#/;
if (root.parentNode && (root.nodeType !== 9) && path.indexOf(',') === -1 && !startIdRe.test(path)) { path = '#' + Ext.escapeId(Ext.id(root)) + ' ' + path; root = root.parentNode; } return single ? [ root.querySelector(path) ] : Ext.Array.toArray(root.querySelectorAll(path)); } catch (e) { }
如果root有父节点,并且root不是document,并且只是单个选择,并且选择文本中不以#开头,那么就将root赋值上ID,进行查询
比如:bar.querySelectorAll('div span a')----> '#bar div span a',进行纠正,但是不支持多个的选择(比如div span a,p div span)
再将root换成root的父节点,这样就解决了问题
Ext.id 方法是获得Element的ID,如果没有ID属性,则赋值一个
Ex.escapeId 是将不合法的ID值进行一个过滤
以后再研究jQuery关于这个BUG的处理。