选取文档元素


大多数客户端 JavaScript 程序运行时总是在操作一个或多个文档元素,为了操作这些文档元素,需要先通过某种方式获取引用文档元素的 Element 对象,DOM 定义了多种方式来获取元素,下面我们来一一讨论:

通过ID选取

任何 HTML 元素都可以有一个 id 属性,在文档中该值必须唯一,即同一个文档不能有两个id相同的元素,可以通过 Document 对象的 getElementById() 方法选取一个基于唯一 id 的元素:

var section = document.getElementById("sectionId");

注:在低于 IE 8 版本的浏览器中,getElementById() 对匹配元素的 id 不区分大小写,而且也返回匹配 name 属性的元素。

通过名字选取

类似 id 属性,name 是给 HTML 元素分配名字,但是与 id 不同,name 属性的值不必唯一,多个元素可能有同样的名字,而且 name 属性只在少数 HTML 元素中有效,包括表单、表单元素、<iframe><img>元素。基于 name 属性值选取 HTML 元素,可以使用 Document 对象的 getElementsByName() 方法:

var radioButton = document.getElementsByName("color");

getElementsByName() 只针对 HTML 文档可用,返回一个 NodeList 对象,该对象类似一个包含若干 Element 对象的只读数组。

注:在 IE 中,getElementsByName() 也返回 id 属性匹配指定值的元素,所以不要将同样的字符同时用作nameid 属性。

在某些 HTML 元素设置 name 属性值将自动为 Window 对象创建对应的全局属性,Document 对象也类似。为 <form><img><iframe><applet><embed><object> 元素设置 name 属性值,就会在 Document 对象中创建以此 name 属性值为名字的属性(假设该文档还没有改名字的属性)。这就意味着这些元素可以作为 Document 属性通过属性名来获取:

var form = document.order; // 针对 <form name="order"> 元素

但是和窗口一样,不推荐这么用这种方式。

通过标签名选取

Document 对象的 getElementsByTagName() 方法可用于获取指定标签名的所有 HTML 元素,比如要获取所有 <span> 元素,可以这么做:

var spans = document.getElementsByTagName("span");

该方法返回的也是 NodeList 对象。

HTML 标签不区分大小写,getElementsByTagName() 方法亦然。

getElementsByTagName() 方法支持传入通配符 *,将获得一个代表文档中所有元素的 NodeList 对象。

Element 对象上也有 getElementsByTagName() 方法,但是只选取调用该方法的元素的后代元素。

由于历史原因,HTMLDocument 类定义了一些快捷属性来访问对应节点,例如 images 属性访问 <img> 元素,forms 属性访问 <form> 元素,links 属性访问 <a> 元素等,这些属性指代 HTMLCollection 对象,它们很像 NodeList 对象,但是可以使用元素的 idname 属性来索引。

此外,HTMLDocument 还定义了 embedsplugins 属性,都是 HTMLCollection 类型的 <embed> 元素集合。anchors 是非标准属性,指代有一个 name 属性的 <a> 元素而不是 href 属性。scripts 在 HTML 5 中是标准属性,它是 HTMLCollection 类型的 <script> 元素的集合。

HTMLDocument 对象还定义了两个属性,document.body 指代 HTML 文档的 <body> 元素,document.head 指代 <head> 元素,这些属性总是会定义,技术源码没有显式包含,浏览器也会隐式创建。

Document 类的 documentElement 属性指代文档的根元素,在 HTML 文档中,它总是指代 <html> 元素。

通过CSS类选取

HTML 的 class 的属性值是一个以空格隔开的列表,可以为空或包含多个标识符。它描述一种方法来定义多组相关的文档元素,在它们的 class 属性中有相同标识符的任何元素属于该组的一部分。在 JavaScript 中 class 是保留字,所以客户端 JavaScript 使用 className 属性来保存 HTML 的 class 属性值。

JavaScript 定义了 getElementsByClassName() 方法,基于 class 属性值中的标识符来选取文档元素,它的返回值也是 NodeList 对象,该方法只需要一个字符串参数,但是该字符串可以是空格隔开的标识符:

// 查找 class 属性值中包含 warnings 的所有元素
var warnings = document.getElementsByClassName("warning");
var log = document.getElementById("log");
// 查找 log 元素后代中 class 属性值包含 fatal 和 error 的所有元素(与顺序无关)
var fatal = document.getElementsByClassName("fatal error");

注:IE 8 及以下版本不支持 getElementsByClassName() 方法。

通过CSS选择器选取

CSS 样式表有一个非常强大的语法,那就是选择器,它用来描述文档中的若干或多组元素。完整的 CSS 选择器规范请参考 https://www.w3.org/TR/selectors-3/,这里只举例演示一些基本语法,比如元素可以用 id、标签名或class来描述:

#nav    // id=nav的所有元素
div     // 所有 <div> 元素
.warning  // 所有class属性值中包含 warning 的元素

元素可以基于属性值选取:

p[lang="en"]   // 所有 <p lang="en"> 段落
*[name="x"]    // 所有包含 name="x" 属性的元素

选择器还可以组合使用:

span.fatal.error   // class 中包含 fatal 和 error 的所有 <span> 元素
span[lang="en"].warning  // 所有class属性值包含warning的<span lang="en">元素

选择器还可以指定文档结构:

#log span     // id="log"后代元素中的所有<span>元素
#log>span     // id="log"子元素中的所有<span>元素
body>h1:first-child  // <body>子元素中的第一个<h1>元素

选择器可以组合起来选取多个元素:

div, #log   // 所有 <div> 元素以及 id=log 的元素

与 CSS3 选择器的标准化一起的另一个称作「选择器API」的 W3C 标准定义了获取匹配一个给定选择器的元素的JavaScript方法(参考https://www.w3.org/TR/selectors-api/),该 API 的关键是 Document 对象方法 querySelectorAll(),它接收一个包含 CSS 选择器的字符串参数,返回一个表示文档中匹配选择器的所有元素的 NodeList 对象。与之前的选取元素的方法不同,该方法返回的 NodeList 对象不是实时的,它包含在调用时刻选择器所匹配的元素,但并不更新后续文档变化,如果没有匹配元素,该方法将返回一个空的 NodeList 对象,如果选择器非法,将抛出一个异常。

除了 querySelectorAll(),文档对象还提供了 querySelector() 方法,不同之处在于后者只返回匹配的第一个元素,如果没有匹配就返回 null

这两个方法在 Element 对象上也有定义,此时,指定的选择器仍然在整个文档中匹配,然后过滤结果集以便只包含指定元素的后代元素。

querySelectorAll() 是终极的选取元素的方法,通过它客户端 JavaScript 可以选择任何想要操作的元素,jQuery 就是使用基于这个 CSS 选择器的查询作为它的核心编程范式,只不过在 jQeury 对其进行封装,对外暴露的是更加轻便的、跨浏览器的 $() 方法。

document.all[]

在 DOM 标准化之前,IE 4 引入了 document.all[] 集合来表示所有文档中的元素(除Text节点),虽然现在已经废弃不用了,但在引入之时它是革命性的。


点赞 取消点赞 收藏 取消收藏

<< 上一篇: DOM 概览

>> 下一篇: 文档结构和遍历