文檔物件模型(DOM)
DOM 代表文檔物件模型,它是 HTML 文檔的節點和物件表示法。瀏覽器提供了一個 API,你可以使用它來與 DOM 進行交互。這就是現代 JavaScript 框架的工作方式 - 它們使用 DOM API 告訴瀏覽器在頁面上顯示什麼。
DOM 是瀏覽器對網頁的內部表示。當瀏覽器從服務器獲取 HTML 時,解析器會分析代碼的結構並創建其模型。基於這個模型,瀏覽器在屏幕上呈現頁面。
瀏覽器提供了一個 API,你可以使用它來與 DOM 進行交互。這就是現代 JavaScript 框架的工作方式 - 它們使用 DOM API 告訴瀏覽器在頁面上顯示什麼。
在單頁應用中,DOM 不斷變化以反映屏幕上的內容,作為開發人員,你可以使用瀏覽器開發者工具來檢查它。
DOM 是無語言限制的,並且訪問 DOM 的事實上的標準方式是使用JavaScript,因為它是瀏覽器唯一能運行的語言。
DOM 由 WHATWG 在 DOM 鏈接規範中進行了標準化。
使用 JavaScript,你可以與 DOM 進行交互的操作包括:
- 檢查頁面結構
- 訪問頁面的元數據和標題
- 編輯 CSS 样式
- 附加或刪除事件監聽器
- 編輯頁面中的任何節點
- 更改任何節點的屬性
.. 還有更多。
DOM API 提供的兩個主要物件是 document
和 window
。
窗口物件
window
物件表示包含 DOM 文檔的窗口。
window.document
指向窗口中加載的 document
物件。
這個物件的屬性和方法可以直接調用,因為它表示全局物件。因此,前面的 window.document
屬性通常被稱為 document
。
屬性
以下是你可能需要經常使用的一些有用屬性的列表:
console
指向瀏覽器的調試控制台。可使用console.log
、console.error
和其他工具(參見瀏覽器開發者工具文章)打印錯誤消息或日誌。document
如前所述,指向document
物件,是你將執行的 DOM 操作的關鍵。history
可以訪問 History APIlocation
可以訪問 Location interface,從中你可以獲取 URL、協議、哈希和其他有用的信息。localStorage
是對 Web Storage API 的 localStorage 物件的引用。sessionStorage
是對 Web Storage API sessionStorage 物件的引用。
方法
window
物件還提供了一些有用的方法:
alert()
:用於顯示警告對話框postMessage()
:被 Channel Messaging API 使用requestAnimationFrame()
:以高效且對 CPU 友好的方式執行動畫setInterval()
:每隔 n 毫秒調用一次函數,直到通過clearInterval()
清除間隔clearInterval()
:清除通過setInterval()
創建的間隔setTimeout()
:在 ‘n’ 毫秒後執行一個函數setImmediate()
:在瀏覽器準備就緒時立即執行一個函數addEventListener()
: 向文檔中添加事件監聽器removeEventListener()
: 從文檔中刪除事件監聽器
在 https://developer.mozilla.org/en-US/docs/Web/API/Window 查看完整的 window
物件的所有屬性和方法參考。
文檔物件
document
物件代表加載在窗口中的 DOM 樹。
以下是指向 head 和 body 標簽的 DOM 的部分表示:
以下是顯示了包含標題的 head 標簽的 DOM 的部分表示:
以下是顯示了包含了一個連結的 body 標簽的 DOM 的部分表示,以及該連結的值和帶有其值的 href 屬性:
可以通過 window.document
獲取 Document 物件,由於 window
是全局物件,所以你可以直接在瀏覽器控制台或 JavaScript 代碼中使用 document
快捷方式直接訪問 document
物件。
該 Document 物件有很多屬性和方法。你最常使用的是選擇器 API的方法:
document.getElementById()
document.querySelector()
document.querySelectorAll()
document.getElementsByTagName()
document.getElementsByClassName()
可以使用 document.title
獲取文檔標題,使用 document.URL
獲取 URL。引用者可以在 document.referrer
中獲取到,域名在 document.domain
中。
從 document
物件中可以獲取 Element 節點 的 body 和 head:
document.documentElement
:Document 節點document.body
:body Element 節點document.head
:head Element 節點
可以通過 document.links
獲取特定類型的所有元素節點的列表,比如所有鏈接的 HTMLCollection,所有圖片使用 document.images
,所有表單使用 document.forms
。
文檔cookies在 document.cookie
中可訪問。最後修改的日期在 document.lastModified
中。
你還可以做更多的事情,甚至可以使用 document.write()
,這是一個在 JavaScript 的早期日子中用於與頁面交互的方法。
在 https://developer.mozilla.org/en-US/docs/Web/API/Document 查看完整的 document
物件的所有屬性和方法參考。
節點類型
DOM 有不同類型的節點,其中一些你在上面的示例圖像中已經見過了。你將遇到的主要節點類型有:
- Document:文檔節點,樹的起點
- Element:HTML 標簽
- Attr:標簽的屬性
- Text:元素或 Attr 節點的文本內容
- Comment:HTML 註釋
- DocumentType:文檔類型聲明
遍歷 DOM
DOM 是具有元素樹結構的樹,文檔節點是樹的根,指向 html
Element 節點,該 Element 節點又指向其子元素節點 head
和 body
,依此類推。
從這些元素中,你可以導航 DOM 結構並移動到不同的節點。
獲取父節點
每個元素都有一個父節點。
要獲取它,可以使用 Node.parentNode
或 Node.parentElement
(其中 Node 表示 DOM 中的一個節點)。
除了在 html
元素上運行時,它們基本上是相同的:parentNode
返回 DOM 樹中指定節點的父節點,而 parentElement
返回節點的 parent Element,如果節點沒有父節點或其父節點不是 DOM 元素,則返回 null。
通常人們使用 parentNode
。
獲取子節點
要檢查節點是否有子節點,使用 **Node.hasChildNodes()
**,它返回一個布爾值。
要訪問節點的所有子元素節點,使用 **Node.childNodes
**。
DOM 還提供了 Node.children
方法。但是,它不僅包括 Element 節點,還包括元素之間的空白空間是文本節點。這通常不是你想要的。
要獲取第一個子元素節點,使用 **Node.firstElementChild
**。要獲取最後一個子元素節點,使用 **Node.lastElementChild
**:
DOM 也公開了 Node.firstChild
和 Node.lastChild
,它們的不同之處在於它們不僅僅“過濾”元素節點的樹。它們還顯示表示空白空間的空白文本節點。
簡而言之,要遍歷子元素節點,使用:
Node.childNodes
Node.firstElementChild
Node.lastElementChild
獲取兄弟節點
除了獲取父節點和子節點之外,由於 DOM 是一個樹,你還可以獲取任何元素節點的兄弟節點。
你可以使用:
Node.previousElementSibling
Node.nextElementSibling
DOM 也公開了previousSibling
和nextSibling
,但正如上面描述的它們的對應物一樣,它們包括空白空間作為文本節點,因此通常應避免使用它們。
編輯 DOM
DOM 提供了各種方法來編輯頁面的節點並修改文檔樹。
使用
document.createElement()
:創建一個新的 Element 節點document.createTextNode()
:創建一個新的 Text 節點
你可以創建新的元素,並將它們添加到 DOM 中作為所需的子元素,使用 document.appendChild()
:
1 | const div = document.createElement('div') |
first.removeChild(second)
:從節點 “first” 中刪除子節點 “second”。document.insertBefore(newNode, existingNode)
:在 DOM 樹結構中的 “existingNode” 之前插入新的兄弟節點 “newNode”。element.appendChild(newChild)
:修改 “element” 下的樹,在所有其他子節點之後添加新的子節點 “newChild”。element.prepend(newChild)
:修改“element”下的樹,在其他子元素之前添加新的子節點“newChild”。可以傳遞一個或多個子節點,甚至可以傳遞一個字符串,該字符串將解釋為 Text 節點。element.replaceChild(newChild, existingChild)
:修改“element”下的樹,在其中用新的節點“newChild”替換“existingChild”。element.insertAdjacentElement(position, newElement)
:按照“position”參數的值,將“newElement”插入到 DOM 中的“element”位置相對應的位置。查看所有可能的值。element.textContent = 'something'
:將 Text 節點的內容更改為“something”。
標籤: DOM, Document Object Model, JavaScript, 瀏覽器, API, HTML