Selector API 是由 W3C 发起制定的一个标准,致力于让浏览器原生支持 css 查询,jquery 库就的核心就是通过 CSS 选择器查询 DOM 文档取得元素的引用,从而抛开了 getElementById() 和 getElementsByTagName() ,然而原生的 Selector API 解析和树查询操作可以在浏览器编译后的代码来完成,极大的改善了性能。
querySelector()
方法传入的参数都是 CSS 选择符,如果没有找到匹配的元素返回 null ,若传入的参数不支持 CSS 选择器,则会抛出错误。
// 取得 id = "myDiv" 的元素
var myDiv = document.querySelector("#myDiv");
// 类似于 jQuery 的 $("#myDiv");
// 取得 class = "selected" 的元素
var selected = document.querySelector(".selected");
// 类似于 jQuery 的 $(".selectes");
querySelectoeAll()
方法返回的不仅仅是一个元素,而是满足匹配的所有元素的 NodeList 的实例,若没有找到匹配的元素,返回一个空的 NodeList ,若传入的参数不符合 CSS 选择器会抛出一个错误。
// 取得<div>中所有的 <em> 元素
var ems = document.getElementById("myDiv").querySelectorAll("em");
// 类似于 jQuery 的 var ems = $("myDiv em");
// 取得 class = "selected" 的所有元素
var selecteds = document.querySelectorAll(".selected");
它返回的 NodeList 中的每一个元素,可以使用 item() 方法,也可以使用方括号的语法,
var ems = document.getElementById("myDiv").querySelectorAll("em");
var em;
for(var i = 0, len = ems.elngth; i < len; i++){
em = ems.item(i); // 或者 ems[i];
em.className = "active";
}
NodeList
- 属性
length : NodeList 对象中包含的结点的个数 - 方法
item( idx ): 返回 NodeList 对象中指定索引的结点,如果索引越界,则返回 null ,等价于 nodeList[dex],不过这种情况下如果索引越界返回 undefined . - 注意
是一个 “有时时事”的集合,大多数情况下,NodeList 是一个时事的集合,如果当文档中的节点数发生变化,则已经存在的 nodeList 对象也可能会变化。例如 Node.childNodes 是实时的:
var parent = decument.getElementById("parent");
var child_nodes = parent.childNodes;
console.log(child_nodes.length); // 假设结果是 2
parent.appendChild(document.createElement("div"));
console.log(child_nodes.length); // 此时的输出为 3
另外一些情况,NodeList 是一个静态集合,也就意味着以后对文档对象模型的任何改动都不会影响集合的内容,document.querySelectorAll() 返回一个静态的 NodeList.
NodeList 不是数组
NodeList 对象在某些方面和数组非常相似,但是 NodeList 没有像数组的一样的那些方法,Array 的类似forEach, map 方法是 Array.prototype 对象的方法,和数组不一样 NodeList 的原型链是 myNodeList->NodeList.prototype->Object.prototype->null . NodeList.prototype 上只有 item() 方法,没有其他的方法,所以用不了数组的方法,但是我们可以用下面的几种解决方法。
扩展 DOM 对象
就是把 Array.prototype 上的方法添加到 NodeList.prototype 上,可是要注意扩展 DOM 对象的原型是非常危险的,尤其是在旧版本的 IE 浏览器中。
var array Methods = Object.getOwnPrototypeNames(Array.prototype);
arrayMethods.forEach(function(methodName){
if(methodName !== 'length'){
NodeList.prototype[methodName] = Array.prototype[methodName];
}
});
var divs = document.getElementsByTagName("div");
var firstDiv = divs[0];
firstDiv.childNodes.forEach(function(divChild){
divChild.parentNode.style.color = '#ccc';
});
不扩展 DOM 对象原型的方法
var forEach = Array.prototype.forEach;
var divs = document.getElementsByTagName("div");
var firstDiv = divs[0];
forEach.call(firstDiv.childNodes, function(){
divChild.parentNode.style.color = '#ccc';
});
将 NodeList 转换为 Array
有时候用类似数组的方法来处理 NodeList 里的内容会更加方便。这里有一种技术为了将 NodeList 对象转换为数组:
var div_list = document.querySelectorAll("div");
var div_array = Array.prototype.slice.call(div_list);