首页 > 代码库 > querySelectorAll的BUG

querySelectorAll的BUG

querySelector和querySelectorAll是W3C提供的新的查询接口

目前 IE8/9及Firefox/Chrome/Safari/Opera 的最新版已经支持它们。

但是Element.querySelectorAll有个bug

  

<div>
    <div id="bar">
		<span>
			<a href="http://www.mamicode.com/###">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的处理。