Javascript中DOM常見API
前言:儘管現在有很多優秀的框架,大大簡化了我們的DOM操作,但是我們仍然要學好DOM知識來寫原生JS,從根本上去理解,才更能在解決問題時舉重若輕。
一、什麼是DOM
D(document)O(object)M(model) 文件物件模型。
DOM(文件物件模型)是HTML和XML文件的程式設計介面。它提供了對文件的結構化的表述,並定義一種方式可以使從程式中對該結構進行訪問,從而改變文件的結構、樣式和內容。DOM將文件解析為一個由節點和物件(包含屬性和方法的物件)組成的結構集合。
上述說法是MDN的解釋,太官方,我們來換種說法來解釋。
DOM就是一種想象的樹形結構,它的作用是將網頁轉為一個 JavaScript 物件,從而可以用指令碼進行各種操作(比如增刪內容)。
如上圖,是我們文件的樹形結構,我們透過DOM模型將上述結構一一對映成節點(透過建構函式把頁面中的節點變成例項物件,dom就是這樣把文件變成物件的),這些節點就又構成了節點樹,也就是我們說的想象中的那棵DOM Tree。
二、Node
DOM 的最小組成單位叫做節點(node)。文件的樹形結構(DOM 樹),就是由各種不同型別的節點組成。
節點主要有7種類型:
Document
:整個文件樹的根節點
Document
:doctype標籤節點,如
<!DOCTYPE html>
Element
:網頁的各種
Html
標籤,比如
等
Attribute
:網頁元素的屬性
Text
:標籤之間或者標籤包含的文字
Comment
:註釋
DocunmentFragment
:文件的片段
所以文件樹對應的節點樹如同下圖:
注:DOM樹有3種層級結構:
父節點關係(parentNode):直接的上級節點
子節點關係(childNodes):直接的下級節點
兄弟關係(sibling):擁有同一個父節點的同級節點
值得注意的是,在上圖中只有根節點也就是
對應的節點沒有父節點。
三、Node介面
瀏覽器提供一個原生的節點物件
Node
,上面的7種節點均繼承了
Node
,因此具有一些共同的屬性和方法。這是DOM操作的基礎。
1、屬性
1.1 Node.prototype.nodeType
nodeType
屬性返回一個整數值,表示節點的型別。
如上圖,我們獲取當前頁面的
body
標籤下的第一個孩子,是一個
div
標籤,然後我們透過
nodeType
來看一下它的節點型別,結果返回了一個數字1,這代表著是一個
Element
節點。
【至於為什麼會是返回一個數字而不是簡單明瞭的返回
Element
,這也是由於歷史原因,早期計算機記憶體緊張,為了節省記憶體使用了並無規律的數字】
常見的有以下:
Node。ELEMENT_NODE
:1
Node。ATTRIBUTE_NODE
:2
Node。TEXT_NODE
:3
Node。COMMENT_NODE
:8
Node。DOCUMENT_NODE
:9
Node。DOCUMENT_TYPE_NODE
:10
Node。DOCUMENT_FRAGMENT_NODE
:11
1.2 Node.prototype.nodeName
nodeName
屬性返回節點名稱
注:在元素節點中,返回名稱基本都是大寫,只有
標籤返回的是小寫。
1.3 Node.prototype.nodeValue
nodeValue
屬性返回一個字串,表示當前節點本身的文字值,該屬性可讀寫。
只有文字節點(text)、註釋節點(comment)和屬性節點(attr)有文字值,因此這三類節點的
nodeValue
可以返回結果,其他型別的節點一律返回
null
。
// html 程式碼如下
//
var
div
=
document
。
getElementById
(
‘d1’
);
div
。
nodeValue
// null
div
。
firstChild
。
nodeValue
//“hello world”
1.4 Node.prototype.textContent
textContent
返回節點及後代節點的文字 ,即獲取文字
這裡和
innerText
一起講:
早期並沒有獲取文字的API ,導致編碼很繁瑣,所以後來IE自己添加了一個API就是
innerText
,然後火狐和opera也推出了
textContent
兩者的區別:
textContent
會獲取所有元素的內容,包括
和
元素,然而
innerText
不會獲取這些內容。
innerText
可以意識到樣式,它不會返回樣式為
display:none
也就是隱藏的文字,而
textContent
會。
由於
innerText
會意識到樣式,也就是會受樣式的影響,因此會觸發重排(reflow)導致效能低,而
textContent
不會。
與
textContent
不同, 在 Internet Explorer (對於小於等於 IE11 的版本) 中對
innerText
進行修改, 不僅會移除當前元素的子節點,而且還會永久性地破壞所有後代文字節點(所以不可能將節點再次插入到任何其他元素或同一元素中)。
1.5 Node.prototype.nextSibling
Node。nextSibling
屬性返回緊跟在當前節點後面的第一個同級節點。如果當前節點後面沒有同級節點,則返回
null
。
值得注意的是,該屬性還包括文字節點和註釋節點(
<!—— comment ——>
)。因此如果當前節點後面有空格或者回車,該屬性會返回一個文字節點,內容為空格或回車。
document。body。nextSibling
返回了文字節點或者註釋節點,而我們需要獲得是元素節點, 也可以用
document。prototype。nextElementSibling
直接獲取該節點後面最接近的同級元素節點。
1.6 Node.prototype.previousSibling
previousSibling
屬性返回當前節點前面的、距離最近的一個同級節點。如果當前節點前面沒有同級節點,則返回
null
。
Node。prototype。previousElementSibling
前一個同級元素節點
其他同1。5 一致
1.7 Node.prototype.firstChild,Node.prototype.firstElementChild
firstChild
屬性返回當前節點的第一個子節點,如果當前節點沒有子節點,則返回
null
。
firstElementChild
屬性返回當前節點的第一個元素節點。
1.8 Node.prototype.lastChild,Node.prototype.lastElementChild
lastChild
屬性返回當前節點的最後一個子節點,如果當前節點沒有子節點,則返回
null
。
lastElementChild
屬性返回當前節點的最後一個元素節點。
1.9 Node.prototype.childNodes
childNodes
屬性返回一個
類似陣列
的物件(
NodeList
集合),成員包括當前節點的所有子節點。
值得注意的是,除了元素節點,
childNodes
屬性的返回值還包括文字節點和註釋節點。如果當前節點不包括任何子節點,則返回一個空的
NodeList
集合。由於
NodeList
物件是一個動態集合,一旦子節點發生變化,立刻會反映在返回結果之中。
1.10 Node.prototype.children
children
屬性返回一個類似陣列的物件(HTMLCollection),成員包括當前節點的所有子元素節點。
值得注意的是,這裡就不會返回文字節點和註釋節點了,它只會返回元素節點。由於
HTMLCollection
集合是動態集合,一旦子節點發生變化,立刻會反映在返回結果之中。
小tips :
Nodelist
和
HTMLCollection
集合的區別
NodeList
可以包含各種型別的節點,
HTMLCollection
只能包含 HTML 元素節點。
NodeList
例項可能是動態集合,也可能是靜態集合。目前,只有
Node。childNodes
返回的是一個動態集合,其他的
NodeList
都是靜態集合。而
HTMLCollection
例項都是動態集合,節點的變化會實時反映在集合中。
與
NodeList
介面不同,
HTMLCollection
沒有
forEach
方法,只能使用
for
迴圈遍歷。
2、方法
2.1 Node.prototype.appendChild()
appendChild
方法就是接受一個節點物件作為引數,將其作為最後一個子節點,插入到當前節點 。該方法的返回值就是插入的子節點。
注意:
1、如果引數節點是 DOM 已經存在的節點,
appendChild
方法會將其從原來的位置移動到新位置。
2、如果
appendChild
方法的引數是
DocumentFragment
節點,那麼插入的是
DocumentFragment
的所有子節點,而不是
DocumentFragment
節點本身。返回值是一個空的
DocumentFragment
。
2.2 Node.prototype.hasChildNodes()
hasChildNodes
方法返回一個布林值,表示當前節點是否有子節點。
注意:子節點包括所有型別的節點,並不僅僅是元素節點。哪怕節點只包含一個空格,
hasChildNodes
方法也會返回
true
判斷一個節點是否有子節點,有以下3種方法:
1、node。hasChildNodes()
2、node。firstChild ! == null
3、node。childNodes && node。childNodes。length > 0
2.3 Node.prototype.cloneNode()
cloneNode
方法複製一個節點,並且可以接受一個布林值,來表示是否同時複製子節點。它的返回值是一個克隆出來的新節點。
深複製:深入進去全部複製,包括子節點。
淺複製:只複製節點本身。
值得注意的是,該方法返回的節點不在文件中,無任何父節點,必須用如
appendChild()
等方法新增。
2.4 Node.prototype.insertBefore()
insertBefore
方法用於將某個節點插入父節點內部的指定位置。
insertBefore
方法接受兩個引數,第一個引數是所要插入的節點
newNode
,第二個引數時父節點
parentNode
內部的一個子節點
referenceNode
。
newNode
將插在
referenceNode
這個子節點的前面。返回值是插入的新節點
newNode
。
2.5 Node.prototype.removeChild()
removeChild
方法接受一個子節點作為引數,用於從當前節點移除該子節點。返回值是移除的子節點。
值得注意的是,被移除的節點依然存在於記憶體之中,但不再是DOM的一部分。所以,一個節點移除以後,依然可以使用它,比如插入到另一個節點下面。
如果引數節點不是當前節點的子節點,
removeChild
方法將報錯。
2.6 Node.prototype.replaceChild()
replaceChild
方法用於將一個新的節點,替換當前節點的某一個子節點。
創造一個新兒子取代掉舊兒子,舊兒子去哪兒了?舊兒子去記憶體了。
2.7 Node.prototype.contains()
contains
方法返回一個布林值,表示引數節點是否為該節點的後代節點。
2.8 Node.prototype.isEqualNode(),Node.prototype.isSameNode()
isEqualNode
方法返回一個布林值,用於檢查兩個節點是否相等。所謂相等的節點,指的是兩個節點的型別相同、屬性相同、子節點相同。
isSameNode
方法返回一個布林值,表示兩個節點是否為同一個節點。
所以說,
isSameNode
就等同於
===
嚴格相等運算子。
2.9 Node.prototype.normalize()
normailize
方法用於清理當前節點內部的所有文字節點(text)。它會去除空的文字節點,並且將毗鄰的文字節點合併成一個,也就是說不存在空的文字節點,以及毗鄰的文字節點
四、Document介面
document
節點物件代表整個文件,每張網頁都有自己的
document
物件。
window。document
屬性就指向這個物件。只要瀏覽器開始載入 HTML 文件,該物件就存在了,可以直接使用。
document
物件有不同的辦法可以獲取。
1、屬性
1。1 用於指向其他節點(快捷獲取某些特殊節點)的屬性
document。doctype
指向
節點,即文件型別節點。
document。documentElement
指向 DOM 的
html
節點
document。activeElement
指向獲得焦點的那個節點
document。fullscreenElement
返回當前以全屏狀態展示的 DOM 元素。
document。body
指向
節點
document。head
指向
節點。
document。scrollingElement
返回文件的滾動元素。
……
1。2 返回文件特定元素的偽陣列集合的屬性
document。links
屬性返回當前文件所有設定了
href
屬性的
及
節點。
document。forms
屬性返回所有