DOM 即文檔對象模型,是操作 HTML/XML 文檔的一套方法。通過 DOM 操作節點,使頁面發生改變,是動態文檔技術的核心內容 ...
JavaScript DOM 基礎
DOM 即文檔對象模型,是操作 HTML/XML 文檔的一套方法。通過 DOM 操作節點,使頁面發生改變,是動態文檔技術的核心內容
DOM 的含義
-
DOM 即 document object model,文檔對象模型
-
JavaScript 中有三類對象
本地對象 Native Object
Object Function String Number Boolean Error EvalError SyntaxError TypeError RageError ReferenceError URIError Date RegExp
內置對象 Built-in Object
Global: 一類對象的統稱,是虛擬的,代表全局 任何方法和屬性都在對象之下 如 isNaN()、parseInt、Number()、decodeURL() 等都是 Global 下的方法 如 Math、Infinity、NaN、undefined 等都是 Global 下的屬性 本地對象、內置對象是 ECMAScript 的內部對象
宿主對象 Host Object
執行 JS 的環境提供的對象,即瀏覽器對象 window 對象 -> BOM,不同瀏覽器間沒有固定規範 document 對象 -> DOM,遵從 w3c 規範 document 是 window 下的對象,即 BOM 包含 DOM
-
DOM 是通過瀏覽器提供的一套方法來操作 HTML 和 XML 文檔
元素和節點
-
節點包含元素,元素是節點的一部分,即元素節點
-
節點分類
元素節點、屬性節點、文本節點、註釋節點、文檔節點等
-
元素即元素對象,有 HTMLDivElement、HTMLInputElement、HTMLHtmlElement,繼承自構造方法 HTMLElement,HTMLElement 繼承自 Node,Node 即節點對象
-
document 繼承自構造方法 HTMLDocument 的原型,HTMLDocument 繼承自 Document 的原型
document.__proto__ -> HTMLDocument.prototype HTMLDocument.prototype.__proto__ -> Document.prototype
獲取元素
-
通過 id 獲取元素
document.getElementById(); // 返回對應的 HTMLElement // 對於 getElementById(),IE8 及以下不區分大小寫並且可以匹配 name
-
通過類名獲取元素集合
document.getElementsByClassName(); // 返回元素集合 HTMLCollection // 相容 IE8 及以上
-
通過標簽名獲取元素集合
document.getElementsByTagName(); // 返回元素集合 HTMLCollection // 相容 IE8 及以上
-
通過 name 獲取元素
document.getElementsByName(); // 返回元素集合 HTMLCollection // 常用於表單元素
-
通過選擇器獲取對象
// 相容 IE6 及以上,是 HTML5 新加入的 web api,但早就存在了 document.querySelector(); // 返回選擇器選中的第一個節點對象 Node document.querySelectorAll(); // 返回選擇器選中的節點列表 NodeList // querySelector、querySelectorAll 性能低 // 使用 querySelectorAll 返回節點列表,刪除節點後,節點列表不變,不具有實時性
遍歷節點樹
-
parentNode
獲取父節點
document.getElementsByTagName("html")[0].parentNode -> document // html 標簽元素的 parentNode 是 document // 最高級節點是 document,document 的父節點是 null
-
childNodes
獲取子節點集合
document.getElementById("box").childNodes // 包括元素節點、文本節點、註釋節點在內
-
firstChild、lastChild
獲取第一個或最後一個子節點
document.getElementById("box").firstChild // 第一個子節點 document.getElementById("box").lastChild // 第二個子節點
-
nextSibling、previousSibling
獲取上一個或下一個兄弟節點
document.getElementById("box").nextSibling // 上一個兄弟節點 document.getElementById("box").previousSibling // 下一個兄弟節點
-
getAttributeNode()
獲取屬性節點
document.getElementById("box").getAttributeNode("id") // 獲取屬性節點 id
遍歷元素節點
-
parentElement
獲取父元素節點,相容 IE9 及以上
document.getElementsByTagName("html")[0].parentElement -> null // html 標簽元素的 parentElement 是 null
-
children
獲取子元素集合,相容 IE8 及以上
document.getElementById("box").children // 只包含元素節點 document.getElementById("box").chilElementCount // children.length
-
firstElementChild、lastElementChild
獲取第或最後一個子元素節點,相容 IE9 及以上
document.getElementById("box").firstElementChild // 第一個子元素節點 document.getElementById("box").lastElementChild // 第二個子元素節點
-
nextElementSibling、previousElementSibling
獲取下一個或上一個兄弟元素節點,相容 IE9 及以上
document.getElementById("box").nextElementSibling // 上一個兄弟元素節點 document.getElementById("box").previousElementSibling // 下一個兄弟元素節點
節點的屬性
-
nodeName
返回節點名稱、只讀
元素節點,元素名稱大寫document.getElementById("box").nodeName // DIV // 文本節點 -> #text // 註釋節點 -> #comment document.nodeName // #document // 文檔節點 -> #document
-
nodeValue
返回節點內容,可讀寫
屬性節點、文本節點、註釋節點可用document.getElementById("box").getAttributeNode('id').nodeValue // box document.getElementById("box").getAttributeNode('id').value // 效果相同
-
nodeType
返回節點類型對應數字,只讀
元素節點 1 屬性節點 2 文本節點 3 註釋節點 8 document 9 DocumentFragment 11
通過 nodeType 封裝 childNodes,篩選出元素節點
function childElementArray(node) { var arr = [], nodes = node.childNodes; for (var i = 0; i < nodes.length; i++) { var item = nodes[i]; if (item.nodeType === 1) { arr.push(item); } } return arr; }
-
attibutes
返回元素節點的屬性節點組成的類數組
document.getElementById("box").attributes[0].nodeValue // 獲取第一個屬性節點的 nodeValue
-
hasChildNodes
返回是否有子節點的布爾值
DOM 結構樹
graph TB A(Node) --> B(Document) A --> C(Element) A --> D(CharacterData) A --> E(Attributes) B --> F(HTMLDocument) D --> G(Text) D --> H(Comment) C --> I(HTMLElement) I --> J(HTMLHtmlElement) I --> K(HTMLHeadElement) I --> L(HTMLDivElement) I --> M(HTML...Element)-
DOM 結構樹顯示了構造方法的繼承關係與原型鏈的走向
-
Document 的原型被 HTMLDocument 繼承,同樣被 XMLDocument 繼承
-
CharacterData 的原型是文本節點和註釋節點的祖先
-
HTMLElement 下有與標簽對應的多種 HTML...Element,用於構造元素節點
-
需要註意的方法
getElementById、getElementsByName 只在 Document 的原型上,只有 document 可以使用
querySelector、querySelectorAll、getElementsByClassName、getElementsByTagName 在 Document 和 Element 的原型上都有,即 document 和元素節點對象都可以使用
var box = document.getElementById("box"); box.getElementById("list"); // 報錯
-
需要註意的屬性
document.bady 、document.head、document.title 繼承自 HTMLDocoment 的原型
document.documentElement 繼承自 Document 的原型
document.bady; // body 標簽元素 document.head; // head 標簽元素 document.title; // title 元素內文位元組點 document.documentElement; // html 標簽元素
節點相關操作
-
document.createElement()
創建元素節點
var div = document.createElement("div"); // 傳入標簽名
-
document.createTextNode()
創建文本節點
-
document.createComment()
創建註釋節點
-
document.createDocumentFragment()
創建一個文檔碎片,向其中添加節點,再將文檔碎片插入文檔中,可以提高性能
-
appendChild()
在節點內部的最後添加子節點,並且具有剪切節點功能
var div = document.createElement("div"), text = document.creaetTextNode("文本"); div.appendChild(text); document.body.appendChild(div);
-
insertBefore(a, b)
在節點內部 a 節點之前插入 b 節點
元素節點沒有 insertAfter 方法,可以進行封裝
Element.prototype.insertAfter = function (target, origin) { var after = origin.nextElementSibling; if (after) { this.insertBefore(target, after); } else this.appendChild(target); } // 相容 IE9 及以上
-
removeChild()
從文檔中刪除子節點,但記憶體中依然保留空間占用
-
remove()
節點調用,刪除自身,可以釋放記憶體
-
replaceChild(a, b)
用 a 節點替換子節點 b
-
innerHTML
可以取值,可以賦值,並且賦值可以解析 HTML 代碼
-
innerText
可以取值,可以賦值,並且將賦值解析成文本節點,標簽符號會被轉碼成字元實體
firefox 老版本不支持,可使用功能相同的 textContent
-
setAttribute(),getAttribute()
設置、獲取屬性
var div = document.createElement("div"); div.setAttribute('id', 'box'); div.getAttribute('id'); // 返回 box
-
dataset
HTML5 中以命名
data-
開頭的屬性,可以通過 dataset 方法訪問// <p data-name="Jett" data-age="22"></p> document.getElementsByTagName("p")[0].dateset // {name: 'Jett', age: '22'} // 相容 IE9 及以上