JavaScript和DOM
- 文件物件模型(DOM)
- 使用 JavaScript 建立內容
- 使用瀏覽器事件
- 效能
DOM
我們將深入瞭解文件物件模型 (DOM) 是什麼、如何建立 DOM,以及如何使用 JavaScript 來訪問它。
DOM 代表“文件物件模型”,是一種樹狀結構,是HTML 文件的表示,反映了元素之間的關係,幷包含元素的內容和屬性。
DOM 不是:
- JavaScript 語言的一部分
DOM 是:
從瀏覽器構建
的- 可以通過
使用 document 物件供 JavaScript 程式碼全域性訪問
如何從 HTML 原始碼轉換為我們在瀏覽器中看到的內容?
瀏覽器處理接受資料的規則,整個流程都由令牌解析器來完成
,當令牌解析器在執行這一流程時,有另一個流程正在消耗這些令牌(token)
,並將它們轉換為節點(node)物件
。例如,我們轉換了第一個 html 令牌並建立了 html 節點,然後消耗第二個令牌並建立 head 節點。
節點之間有關係嗎?是的,注意令牌解析器發出了起始令牌和結束令牌,這樣就可以顯示節點之間的關係
。StartTag: head 令牌出現在 EndTag: html 令牌前面,表示 head 令牌是 html 令牌的子級。類似的 meta 和 link 節點是 head 節點的子級,等等,就形成了穩定物件模型(DOM)
。
它是一個樹結構(tree structure)
,表示 html 的內容和屬性
,以及節點之間的關係
(子級),注意這些物件包含所有的屬性
。DOM 是 HTML 標記的完整解析表示。
總結上述整個過程步驟:
- 收到 HTML
- HTML 標籤被轉換為令牌
- 令牌被轉換為節點
- 節點被轉換為 DOM
當你請求一個網站時,無論該網站的後端語言是什麼,它都會用 HTML 進行響應
。瀏覽器會接收到一連串的 HTML。這些位元組通過一個複雜的(但完全記錄在案的)解析過程
來執行,該過程可以確定不同的字元(例如開始標籤字元 <
,像 href
這樣的屬性,像 >
這樣的右尖括號)。解析發生後,接下來是一個稱為標記化的過程
。標記化過程每次使用一個字元來構建令牌
。這些令牌包括:
- 文件型別(DOCTYPE)
- 開始標籤(StartTag)
- 結束標籤(EndTag)
- 註釋(Comment)
- 字元(Character)
- 檔案結束(End-of-file)
在這個階段,瀏覽器已經收到了伺服器傳送的位元組,並將位元組轉換為標籤,然後讀取了所有標籤,進而建立了一個令牌列表。這個令牌列表將會通過樹構建階段。這個階段的輸出結果是一個樹狀結構
——這就是 DOM!
一個樹狀結構,反映了 HTML 的內容和屬性,以及節點之間的所有關係。
DOM 是 HTML 的完整解析表示。
DOM 是所接收到的 HTML 文件的關係和屬性的模型(描述)。請記住,DOM 代表“文件物件模型”,文件的物件模型
。可以使用瀏覽器提供的一個特殊物件來訪問 DOM:document
,這個物件不是由 JavaScript 語言提供的,但應該已經存在,並且可供 JavaScript 程式碼自由訪問。
DOM 由 W3C 組織進行標準化。有很多組成 DOM 的規範,以下是其中幾個:
- 核心規範
- 事件規範
- 樣式規範
- 驗證規範
- 載入和儲存規範
之前我們學習瞭如何通過 ID(#
)、類(.
)和標籤(如 p
)來選擇頁面元素。接下來,我們將學習如何使用 JavaScript 和 DOM 來訪問頁面元素!
通過 ID 選擇頁面元素
document
是一個物件,就像一個 JavaScript 物件一樣,這意味著它有鍵/值對
。有些值只是資料片段
,而其他值則是可以提供某種功能的函式
(也稱為方法!)。
document.getElementById('idName');
我們需要將一個字串
傳遞給 .getElementById()
,寫明我們希望它查詢並返回給我們的元素
的 ID。瞭解更多有關此方法
關於這種方法,有幾件重要的事情需要記住:
- 它在
document
物件上被呼叫 - 它會返回單個專案
MDN 上的 .getElementById()
通過類或標籤選擇頁面元素
由於 ID 是唯一的,而且在 HTML 中只有一個元素具有該 ID,因此 document.getElementById()
最多隻會返回一個元素。那麼,我們如何選擇多個 DOM 元素呢?
接下來我們將要介紹的兩個 DOM 方法都會返回多個元素,它們是:
.getElementsByClassName()
.getElementsByTagName()
關於這兩種方法,有幾件重要的事情需要記住:
- 兩種方法都使用
document
物件 - 二者都會返回多個專案
所返回的列表(html集合)不是陣列
,特殊的列表,叫做NodeList
通過類來訪問元素
我們需要使用一個希望讓它搜尋/返回的類字串
來呼叫:
document.getElementsByClassName('brand-color');
.getElementById()
與 .getElementsByClassName()
和 .getElementsByTagName()
二者不同的一點,因為這一點很容易被忽視。那就是,.getElementsByClassName()
和 .getElementsByTagName()
的名稱中都多了一個“s”。
通過標籤來訪問元素
document.getElementsByTagName('p');
節點、元素和介面
節點介面
順序 | 專案 |
---|---|
首先發生 | 標籤(tag) |
第二發生 | 令牌(token) |
第三發生 | 節點(nodes) |
第四發生 | DOM |
DOM 是如何構建的?
- 字元
- 標籤
- 令牌
- 節點
- DOM
“節點(Node)”究竟是什麼?
Node = Class // N 大寫表示類
node = object // n 小寫表示物件
Node 就像建築的藍圖。該藍圖包含建築資料,我們稱之為屬性
。它具有一系列的建築功能,我們稱之為方法
。某些屬性可能是建築顏色、門的數量或者窗戶的數量。某些方法可能是保護建築安全的警報系統或者為草澆水的噴灑系統。假設這個藍圖是很多真實建築的模型,替代藍圖的另一個術語是介面
。介面會告訴我們應用到單個專案的屬性和方法。
介面用來表示一系列被繼承的屬性和方法
。
節點(Node)是一個藍圖,包含有關真實節點(nodes)所有屬性和方法的資訊。
節點介面
是每個真實節點
建立後的所有屬性(資料)和方法(功能)的藍圖。節點介面有很多屬性和方法,但它不是很具體
。這就好像,“建築藍圖”沒有“房屋藍圖”或“摩天大樓藍圖”那麼具體。後者是更具體的藍圖,而這些更具體的藍圖可能會有自己的屬性和方法,這些屬性和方法只針對房屋或只針對摩天大樓。
元素介面(Element)
正如節點介面一樣,元素介面是用於建立元素的藍圖:MDN 上的元素介面
元素指向其父代-節點,即元素介面是節點介面的子代
。這也表明元素介面繼承了所有節點介面的屬性和方法。這意味著,從元素介面建立的任何元素(element,小寫“e”!)同時也是節點介面的子代
。也就是說,元素(element,小寫“e”!)同時也是節點(node,小寫“n”!)
。
元素介面有自己的 .getElementsByClassName()
,它和 document
物件上的同名方法具有完全相同的功能。這意味著,你可以使用 document 物件來選擇一個元素
,然後你可以對該元素呼叫 .getElementsByClassName()
,從而接收到一系列帶有該類名的元素
,它們都是該特定元素的子代!
// 選擇 ID 為 "sidebar" 的 DOM 元素
const sidebarElement = document.getElementById('sidebar');
// 在 "sidebar" 元素中找尋任何具有 "sub-heading" 類的元素
const subHeadingList = sidebarElement.getElementsByClassName('sub-heading');
要檢視所有不同的介面,請參見:Web API 介面
更多訪問元素方法
幾乎 MDN 上的每個方法都有一個瀏覽器相容性
表格,列出了每個瀏覽器開始支援該特定方法的時間。值得慶幸的是,所有瀏覽器基本上都支援官方標準
。
但在過去,情況並非如此。你必須編寫不同的程式碼,才能在不同的瀏覽器中執行相同的操作。而且,你還得編寫程式碼來檢查所使用的瀏覽器型別,才能為該瀏覽器執行正確的程式碼。幾個 JavaScript 庫應運而生,以幫助緩解這些問題。 jQuery庫 的主要作用之一是抽象畫不同瀏覽器之間的區別。作為開發者,編寫特定的 jQuery 方法,然後 jQuery 會判斷執行的是哪個瀏覽器並針對該瀏覽器使用正確的程式碼。因為jQuery 使我們可以非常輕鬆地編寫可在多個瀏覽器中正確執行的程式碼
。
querySelector 方法
// 找尋並且返回 ID 名為 "header" 的元素
document.querySelector('#header');
// 找尋並且返回第一個 類 名為 "header" 的元素
document.querySelector('.header');
// 找尋並返回第一個 <header> 元素
document.querySelector('header');
請檢視 MDN 上的 .querySelector() 方法:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/querySelector
注意,我想指出一個潛在的棘手問題,那就是 .querySelector()
方法只會返回一個元素
。如果你使用它通過 ID 搜尋元素,這是很合理的。但是,儘管 .getElementsByClassName()
和 .getElementsByTagName()
都會返回多個元素的列表
,使用 .querySelector()
執行類選擇器或標籤選擇器仍會只返回它所找到的第一個專案。
querySelectorAll 方法
.querySelector()
方法只會返回 DOM 中的一個元素(如果存在的話)。但是,確實有些時候你會想要獲取具有特定類的所有元素列表
,或某種型別的所有元素(例如所有 <tr>
標籤)。我們可以使用 .querySelectorAll()
方法來做到這一點!
// 找尋並返回所有 類 名為 "header" 的元素列表
document.querySelectorAll('.header');
// find and return a list of <header> elements
// 找尋並返回所有 <header> 的元素列表
document.querySelectorAll('header');
當獲得所有元素列表(NodeList)後,因為它不是陣列,我們無法使用陣列方法 .map
迴圈訪問列表中的專案。但 NodeList 提供了 forEach
方法和陣列方法 forEach
非常相似,但是並非所有瀏覽器都完全支援 forEach
方法。
如果要迴圈訪問列表中的專案,可以使用 for 迴圈。首先將返回的所有元素儲存在變數中:
const listOfElements = document.querySelectorAll('h2');
for(let I = 0; I < listOfElements.length; I++) {
console.log(listOfElements[I]);
}
請參見 MDN 上的 .querySelectorAll()
方法:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/querySelectorAll
相關文章
- JavaScript HTML DOMJavaScriptHTML
- 理解JavaScript中BOM和DOM的關係JavaScript
- JavaScript HTML DOM 物件JavaScriptHTML物件
- JavaScript css-domJavaScriptCSS
- JavaScript DOM文件物件JavaScript物件
- JavaScript DOM、BOM操作JavaScript
- 關於dom(javascript)JavaScript
- 不妨這樣去理解JavaScript中的dom和bomJavaScript
- JavaScript的基礎語法及DOM元素和事件JavaScript事件
- JavaScript DOM位置尺寸APIJavaScriptAPI
- JavaScript之DOM查詢JavaScript
- JavaScript 之 DOM [ Document物件 ]JavaScript物件
- JavaScript HTML DOM Canvas 物件JavaScriptHTMLCanvas物件
- JavaScript(ECMAScript+BOM+DOM)JavaScript
- javaScript事件,Bom,Dom物件JavaScript事件物件
- JavaScript中的瀏覽器檢測和DOM基礎JavaScript瀏覽器
- JavaScript中的DOM和Timer(簡單易用的基本操作)JavaScript
- JavaScript基礎之DOM操作JavaScript
- JavaScript的組成 | DOM/BOMJavaScript
- JavaScript5:常用DOM操作JavaScript
- 回到基礎:理解 JavaScript DOMJavaScript
- JavaScript 複習之DOM 概述JavaScript
- JavaScript操作DOM常用的APIJavaScriptAPI
- 【JavaScript】DOM之樣式操作JavaScript
- JavaScript 操作DOM效能優化JavaScript優化
- JavaScript入門⑦-DOM操作大全JavaScript
- 1.14 JavaScript5:常用DOM操作JavaScript
- JavaScript 基礎(四) – HTML DOM EventJavaScriptHTML
- JavaScript ----- 操作DOM物件的屬性JavaScript物件
- DOM和BOM
- jQuery和DOMjQuery
- 學習前端你必須知道的JavaScript 基礎和HTML DOM前端JavaScriptHTML
- javascript避免dom事件重複觸發JavaScript事件
- [譯]13 種有用的 JavaScript DOM 操作JavaScript
- 前端筆記之JavaScript(十)深入JavaScript節點&DOM&事件前端筆記JavaScript事件
- JavaScript基礎 —— DOM:遍歷 與 範圍JavaScript
- JavaScript教程全套影片合集:DOM動畫效果JavaScript動畫
- React 事件和 Dom 事件React事件