本系列的介紹中提到:「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 可讓您深入瞭解 UI 的目前狀態。HTML API 可以存取所有這類資訊。您可以使用 HTMLMediaElement.duration
、HTMLMediaElement.currentTime
和 HTMLMediaElement.ended
分別取得影片長度、當前播放的觀看次數,以及影片 (或音訊) 是否已播放完畢。
可用的元素介面
我們在本系列文章中介紹的大部分 HTML 元素 (以及尚未介紹的元素),除了部分區隔元素外,都有相關聯的 DOM 介面。所有元素的基本介面恰好命名為「Element」。HTMLElement
繼承自 Element,而所有 HTML 元素專屬介面都繼承自 Element。部分元素專屬介面是由多個類似元素實作。
這些介面包括:
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」,後面接著以大寫駝峰式大小寫的元素或元素群組,接著是「Element」,但元素或元素群組部分並未遵循確切的模式。請放心,您不必記住這些值。但請務必瞭解這些設定的存在,以便在需要時查詢。
如果您有元素集合,也會有集合介面。舉例來說,HTMLCollection.namedItem()
方法會傳回集合中第一個 id
或 name
屬性與參數相符的元素,如果沒有相符的元素,則會傳回空值。
除了 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
則具有長度屬性 (僅由 options
屬性傳回),可提供讀取和寫入存取權。<select>
HTMLOptionsCollection
可用於設定集合大小。
其他介面
還有其他介面可用於操控 DOM 節點的分支位置。EventTarget
介面會提供 addEventListener()
和 removeEventListener()
,並由 Node
和 Window
介面繼承。反過來說,Element、Document 和 DocumentFragment (我們在自訂元素中看到的) 介面會繼承自 Node,而 HTMLElement 介面則會繼承自 Element。
node
介面
每個 DOM 節點類型都會以 Node
為基礎的介面表示,該介面會提供與 DOM 樹狀結構相關的元素資訊和方法。Node
介面可讓您查詢節點樹狀結構,並新增節點。
Douglas Crockford 的著名「walk the 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 介面的一種方法。此外,Shadow DOM API 也有 shadowRoot
介面,可單獨從文件的主要 DOM 樹狀結構中算繪。
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 物件。視窗介面可查詢分頁的內容,以及整體視窗和裝置。舉例來說,您可以使用 resizeTo()
方法調整瀏覽器視窗大小,而 devicePixelRatio
屬性則可讓您存取裝置顯示畫面的像素。當您存取內容所在分頁的資訊,而非分頁顯示的 DOM 樹狀結構時,窗格很可能是您要尋找的介面。
您可以使用多個 API,這些 API 可根據透過 Window 介面顯示的功能運作,包括 Web Workers 和 IndexedDB API。
進行隨堂測驗
測驗您對 HTML API 的相關知識。
DOM 中的 O 代表什麼?
哪個介面可以協助您瞭解內容所在分頁的相關資訊?