本系列的介绍中指出,“HTML 元素是构成文档对象模型的节点”。我们已经讨论了元素节点的类型。在本部分中,我们将介绍用于查询这些节点的元素 API。
DOM 和 AOM
DOM 是一个用于访问和操作文档的 API。DOM 是文档中所有节点的树。有些节点可以有子节点,有些则不可以。该树包含元素及其属性和文本节点。
浏览器工具不会提供上述树状可视化图表,但您可以在元素检查器中看到这些节点。
在浏览器开发者工具中可检查的树形表示法是无障碍树。AOM 基于 DOM;同样,无障碍树包含代表所有标记元素、属性和文本节点的对象:
HTML 元素 API
DOM 的中间字母是“object”。就像大多数面向对象编程入门课程中的 person
或 car
对象示例一样,文档树中的每个节点都是一个可使用 JavaScript 操控的对象。
该浏览器提供了许多 API,可提供原生支持的方法、事件以及属性查询和更新。元素节点包含与元素上设置的所有属性相关的信息。您可以使用 HTML 接口来访问有关元素属性的信息。例如,我们可以使用 HTMLImageElement.alt
获取所有图片的 alt
属性:
let allImages = document.querySelectorAll('img');
allImages.forEach((imageInstance) => {
console.log(imageInstance.alt);
});
HTML 接口不仅可让您访问元素的属性,还可让您访问更多信息。我们可以找到只读的 HTMLElement.offsetHeight
,以获取网页中相对于布局的每个版块的高度。
let allSections = document.querySelectorAll('section');
allSections.forEach((sectionInstance) => {
console.log(sectionInstance.offsetHeight);
});
如果用户更改设备屏幕方向或以其他方式更改视口的宽度,每个 <section>
的高度都会发生变化,并且 DOM 属性也会随之自动更新。
HTML 接口 API 不仅可用于访问属性值。DOM 可让您深入了解界面的当前状态。HTML API 可以访问所有这些信息。您可以分别通过 HTMLMediaElement.duration
、HTMLMediaElement.currentTime
和 HTMLMediaElement.ended
访问视频的长度、当前播放的观看位置,以及视频(或音频)是否已播放完毕。
可用的元素接口
除了一些分区元素外,本系列中到目前为止介绍过的以及尚未介绍的大多数 HTML 元素都具有关联的 DOM 接口。所有元素的基准接口恰当地命名为 Element。HTMLElement
继承自 Element,所有 HTML 元素专用接口都继承自它。某些特定于元素的接口由多个类似元素实现。
接口包括:
HTMLAnchorElement
-<a>
HTMLAreaElement
-<area>
HTMLAudioElement
-<audio>
HTMLBaseElement
-<base>
HTMLButtonElement
-<button>
HTMLCanvasElement
-<canvas>
HTMLDataElement
-<data>
HTMLDataListElement
-<datalist>
HTMLDetailsElement
-<details>
HTMLDialogElement
-<dialog>
HTMLEmbedElement
-<embed>
HTMLFieldSetElement
-<fieldset>
HTMLFormElement
-<form>
HTMLHtmlElement
-<html>
HTMLIFrameElement
-<iframe>
HTMLImageElement
-<img>
HTMLInputElement
-<input>
HTMLLabelElement
-<label>
HTMLLegendElement
-<legend>
HTMLLIElement
-<li>
HTMLLinkElement
-<link>
HTMLMapElement
-<map>
HTMLMediaElement
-<audio>
,<video>
HTMLMenuElement
-<menu>
HTMLMetaElement
-<meta>
HTMLMeterElement
-<meter>
HTMLModElement
-<ins>
,<del>
HTMLObjectElement
-<object>
HTMLOListElement
-<ol>
HTMLOptGroupElement
-<optgroup>
HTMLOptionElement
-<option>
HTMLOutputElement
-<output>
HTMLPictureElement
-<picture>
HTMLProgressElement
-<progress>
HTMLQuoteElement
-<q>
、<blockquote>
、<cite>
HTMLScriptElement
-<script>
HTMLSelectElement
-<select>
HTMLSlotElement
-<slot>
HTMLSourceElement
-<source>
HTMLStyleElement
-<style>
HTMLTableCellElement
-<td>
,<th>
HTMLTableColElement
-<col>
,<colgroup>
HTMLTableElement
-<table>
HTMLTableRowElement
-<tr>
HTMLTableSectionElement
-<thead>
、<tbody>
、<tfoot>
HTMLTemplateElement
-<template>
HTMLTextAreaElement
-<textarea>
HTMLTimeElement
-<time>
HTMLTitleElement
-<title>
HTMLTrackElement
-<track>
HTMLVideoElement
-<video>
命名惯例为“HTML”后跟大驼峰式命名的元素或元素分组,再跟“元素”,但元素或元素分组部分没有遵循确切的模式。不必担心,您无需记住这些内容。 只需知道它们的存在即可,以便在需要时查找它们。
如果您有一系列元素,则还可以使用一些集合接口。例如,HTMLCollection.namedItem()
方法会返回集合中 id
或 name
属性与参数匹配的第一个元素;如果没有元素匹配,则返回 null。
除 HTMLElement
外,超过 30 个元素没有关联的 DOM 接口,其中包括 <address>
、<article>
、<section>
、<nav>
、<header>
、<footer>
、<aside>
和 <hgroup>
。许多不支持任何非已废弃的非全局属性的元素都有元素专用接口,例如 HTMLPElement
(<p>
元素)和 HTMLUnknownElement
(<😃>
或任何其他未定义的元素),但这些接口不会在从 HTMLElement
继承的属性和方法之上实现任何其他属性或方法,并且未列在上面。
冗余的 API 方法和属性
如果接口与其继承的接口具有相同的方法或属性名称,则继承的方法或属性会覆盖被继承的方法或属性。换句话说,父级方法和属性会替换子级方法和属性。当我们使用 imageInstance.alt
和 sectionInstance.offsetHeight
分别访问 HTML 元素 API 中的 alt
和 offsetHeight
属性时,代码无法识别正在访问哪个 API。通常,就像这两个示例一样,这不是问题。
不过,在某些情况下,冗余可能会导致问题。例如,HTMLCollection.length
是只读的,而继承接口 HTMLOptionsCollection
具有具有读写权限的长度属性(仅由 <select>
的 options
属性返回)。HTMLOptionsCollection
可用于设置集合大小。
其他接口
还有一些其他接口可用于操控 DOM 节点的分支位置。EventTarget
接口会向我们提供 addEventListener()
和 removeEventListener()
,并会被 Node
和 Window
接口继承。反过来,Element、Document 和 DocumentFragment(我们在自定义元素中曾介绍过)接口会继承自 Node,而 HTMLElement 接口会继承自 Element。
node
接口
每种类型的 DOM 节点都由基于 Node
的接口表示,该接口会提供与 DOM 树相关的元素的信息和方法。Node
接口支持查询节点树并向其添加节点。
Douglas Crockford 的著名“遍历 DOM”函数使用了 Node 的 firstChild
和 nextSibling
属性。
const walk_the_DOM = function walk(node, callback) {
callback(node);
node = node.firstChild;
while (node) {
walk(node, callback);
node = node.nextSibling;
}
};
我们在定义自定义元素时使用了 Node 的 appendChild()
和 cloneNode()
方法。Node 接口提供了许多用于查询和操作 DOM 的实用属性和方法。
customElements.define('star-rating',
class extends HTMLElement {
constructor() {
super(); // Always call super first in constructor
const starRating = document.getElementById('star-rating-template').content;
const shadowRoot = this.attachShadow({
mode: 'open'
});
shadowRoot.appendChild(starRating.cloneNode(true));
}
});
attachShadow()
方法是 Element 接口的方法。此外,还有一个 shadowRoot
接口,用于与文档的主 DOM 树分开呈现的 Shadow DOM API。
Document
和 HTMLDocument
接口
Document
接口继承自 Node
。它表示在浏览器中加载的网页,无论文档是 HTML、SVG、XML、MathML 还是其他格式。Document
接口还会继承自 HTMLDocument
接口。
document
可让您快速访问节点类型,并能够创建特定元素类型(例如 document.body
和 document.styleSheets
)的集合。借助 HTMLDocument,您可以访问与文档相关但未在 HTML 节点中找到的信息,例如 Document.location
、Document.lastModified
和 Document.Cookie
。
您可以根据通过文档界面显示的功能使用多种 API,包括 Drag and Drop API 和 FullScreen API。两者均继承自 Element
。
Window
接口
Window 接口除了 DOM 之外,还包含可用于操控 DOM 的全局可用项。Window 提供了 MDN 的 JavaScript 和 DOM 参考文档中记录的函数、命名空间、对象和构造函数。
Window 接口是包含文档的对象的 API。全局 window
对象是脚本运行的窗口。每个浏览器标签页都包含自己的 Window 对象。Window 接口可以查询标签页的内容以及整个窗口和设备。例如,resizeTo()
方法可用于调整浏览器窗口的大小,devicePixelRatio
属性可用于访问设备显示屏像素。当您访问内容所在的标签页(而非标签页显示的 DOM 树)的相关信息时,该窗口可能是您要查找的界面。
您可以根据通过 Window 接口提供的功能使用多种 API,包括 Web Worker 和 IndexedDB API。
检查您的理解情况
测试您对 HTML API 相关知识的掌握情况。
DOM 中的 O 代表什么?
哪个界面可以帮助您了解内容所在的标签页的相关信息?