11.1 选择符API
众多JavaScript 库中最常用的一项功能,就是根据CSS 选择符选择与某个模式匹配的DOM 元素。
实际上,jQuery(www.jquery.com)的核心就是通过CSS 选择符查询DOM文档取得元素的引用,从而抛开了getElementById()和getElementsByTagName()。Selectors API(www.w3.org/TR/selectors-api/)是由W3C 发起制定的一个标准,致力于让浏览器原生支持CSS 查询。所有实现这一功能的JavaScript 库都会写一个基础的CSS 解析器,然后再使用已有的DOM 方法查询文档并找到匹配的节点。尽管库开发人员在不知疲倦地改进这一过程的性能,但到头来都只能通过运行JavaScript 代码来完成查询操作。而把这个功能变成原生API 之后,解析和树查询操作可以在浏览器内部通过编译后的代码来完成,极大地改善了性能。
Selectors API Level 1 的核心是两个方法:querySelector()和querySelectorAll()。在兼容的浏览器中,可以通过Document 及Element 类型的实例调用它们。目前已完全支持Selectors API Level 1的浏览器有IE 8+、Firefox 3.5+、Safari 3.1+、Chrome 和Opera 10+。
11.1.1 querySelector()方法
querySelector()方法接收一个CSS 选择符,返回与该模式匹配的第一个元素,如果没有找到匹配的元素,返回null。请看下面的例子。
//取得body 元素 var body = document.querySelector("body"); //取得ID 为"myDiv"的元素 var myDiv = document.querySelector("#myDiv"); //取得类为"selected"的第一个元素 var selected = document.querySelector(".selected"); //取得类为"button"的第一个图像元素 var img = document.body.querySelector("img.button");运行一下
通过Document 类型调用querySelector()方法时,会在文档元素的范围内查找匹配的元素。而通过Element 类型调用querySelector()方法时,只会在该元素后代元素的范围内查找匹配的元素。
CSS 选择符可以简单也可以复杂,视情况而定。如果传入了不被支持的选择符,querySelector()会抛出错误。
11.1.2 querySelectorAll()方法
querySelectorAll()方法接收的参数与querySelector()方法一样,都是一个CSS 选择符,但返回的是所有匹配的元素而不仅仅是一个元素。这个方法返回的是一个NodeList 的实例。
具体来说,返回的值实际上是带有所有属性和方法的NodeList,而其底层实现则类似于一组元素的快照,而非不断对文档进行搜索的动态查询。这样实现可以避免使用NodeList 对象通常会引起的大多数性能问题。
只要传给querySelectorAll()方法的CSS 选择符有效,该方法都会返回一个NodeList 对象,而不管找到多少匹配的元素。如果没有找到匹配的元素,NodeList 就是空的。
与querySelector()类似,能够调用querySelectorAll()方法的类型包括Document、DocumentFragment 和Element。下面是几个例子。//取得某<div>中的所有<em>元素(类似于getElementsByTagName("em")) var ems = document.getElementById("myDiv").querySelectorAll("em"); //取得类为"selected"的所有元素 var selecteds = document.querySelectorAll(".selected"); //取得所有<p>元素中的所有<strong>元素 var strongs = document.querySelectorAll("p strong");
要取得返回的NodeList中的每一个元素,可以使用item()方法,也可以使用方括号语法,比如:
var i, len, strong; for (i = 0, len = strongs.length; i < len; i++) { strong = strongs[i]; //或者strongs.item(i) strong.className = "important"; }
同样与querySelector()类似,如果传入了浏览器不支持的选择符或者选择符中有语法错误,querySelectorAll()会抛出错误。
11.1.3 matchesSelector()方法
Selectors API Level 2 规范为Element 类型新增了一个方法matchesSelector()。这个方法接收一个参数,即CSS 选择符,如果调用元素与该选择符匹配,返回true;否则,返回false。看例子。
if (document.body.matchesSelector("body.page1")){ //true }
在取得某个元素引用的情况下,使用这个方法能够方便地检测它是否会被querySelector()或querySelectorAll()方法返回。
截至2011 年年中,还没有浏览器支持matchesSelector()方法;不过,也有一些实验性的实现。
IE 9+通过msMatchesSelector()支持该方法,Firefox 3.6+通过mozMatchesSelector()支持该方法,Safari 5+和Chrome 通过webkitMatchesSelector()支持该方法。因此,如果你想使用这个方法,最好是编写一个包装函数。
function matchesSelector(element, selector) { if (element.matchesSelector) {return element.matchesSelector(selector); } else if (element.msMatchesSelector) {return element.msMatchesSelector(selector); } else if (element.mozMatchesSelector) {return element.mozMatchesSelector(selector); } else if (element.webkitMatchesSelector) {return element.webkitMatchesSelector(selector); } else {throw new Error("Not supported."); } } if (matchesSelector(document.body, "body.page1")) { //执行操作 }运行一下