querySelector和querySelectorAll同属于Selectors API Level 1规范,该规范早在2006年就已经开始发展,并在2007年10月形成querySelector(All)的雏形。由于规范发展的够早,所以除了IE6、 7以外,所有浏览器都基本支持。这两个方法可以作用到Element、Document、DocumentFragment实例上面,即:
var elem = document.getElementById("test"), frag = document.createDocumentFragment(); frag.appendChild(document.createElement("div")); elem.querySelector("p");// Element, querySelectorAll document.querySelector("div");// Document, querySelectorAll document.body.querySelector("div");// querySelectorAll frag.querySelector("div");// documentFragment, querySelectorAll
方法接收唯一的一个参数,该参数可为任意合法的CSS选择器字符串。不过在IE8下,对于大部分的CSS3选择器都不支持(只支持相邻兄弟element1~element2;属性选择器
[attr^=val]
, [attr$=val]
,[attr*=val]
)。除此之外,如果想要在IE8下使用伪元素选择器,需要用:,而不是CSS3规定的::(css3选择器的浏览器支持参考:http://caniuse.com/#search=nth-of-type)。
Selectors API返回的内容是静态的NodeList,这和get系列、document.images返回动态的集合(NodeList、HTMLCollection)是不一样的。
Selectors API虽然好用,不过在使用的时候还是需要注意一些问题。以下面代码为例:
<body> <div id="test"><p>test</p></div> </body>
var ele = document.getElementById("test"); ele.querySelector("div p").length; // A jQuery(ele).find("div p").length; // B ele.querySelector("body p").length; // C jQuery(ele).find("body p").length; // D
对于代码A,返回值为1,;代码B,返回值为0。代码C,返回值仍为1;代码D,返回值为0。(结果适用于所有支持Selectors API的浏览器)
对于习惯使用jQuery的人来说,上面的结果可能有点接受不了。不过在规范中明确写明:
Even though the method is invoked on an element, selectors are still evaluated in the context of the entire document. In the following example, the method will still match the
div
element's childp
element, even though thebody
element is not a descendant of thediv
element itself.var div = document.getElementById("bar"); var p = div.querySelector("body p");
![](http://images.cnitblog.com/blog/632292/201411/102118194756460.png)
// qSA works strangely on Element-rooted queries // We can work around this by specifying an extra ID on the root // and working up from there (Thanks to Andrew Dupont for the technique) // IE 8 doesn't work on object elements } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { var old = context.id, id = context.id = "__sizzle__"; try { return makeArray( context.querySelectorAll( "#" + id + " " + query ), extra ); } catch(pseudoError) { } finally { if ( old ) { context.id = old; } else { context.removeAttribute( "id" ); } } }
不过,如果文档中真的有的元素id为“__sizzle__”,这个方法应该就会悲剧了。
在zepto中,并没有针对elem使用querySelector(All)时的特殊处理,So:
<!DOCTYPE html> <html> <head> <script src="http://zeptojs.com/zepto.min.js"></script> <meta charset="utf-8"> <title>JS Bin</title> </head> <body> <div id="a"><div><p></p></div></div> </body> <script> var ele = Zepto("#a").find("body div div p"); alert(ele.length); // 1 </script> </html>