展。2008 年之前,浏览器中几乎所有的DOM 扩展都是专有的。此后,W3C 着手将一些已经
成为事实标准的专有扩展标准化并写入规范当中。
对DOM 的两个主要的扩展是Selectors API(选择符API)和HTML5。这两个扩展都源自开发社区,
而将某些常见做法及API 标准化一直是众望所归。此外,还有一个不那么引人瞩目的Element Traversal
(元素遍历)规范,为DOM 添加了一些属性。虽然前述两个主要规范(特别是HTML5)已经涵盖了大
量的DOM 扩展,但专有扩展依然存在。本章也会介绍专有的DOM 扩展。
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")){
//执行操作
}