DOM API簡析
DOM API簡析
DOM釋義
API通俗的來講,就是人家提供給你的,讓你可以直接使用的東西。DOM,Document Object Model,文件物件模型。這裡的文件以前特指xml文件,這也就是我們在html裡邊使用DOM API那麼難用的原因,它一開始就不是給html使用的。
所謂Document Object Model,本質上還是一種model,將document(xml、html)變成object的model。所以我們所理解的DOM,就是把html文件變成一種具有樹形結構object的規則。我們寫一個最簡單的html文件如下:
<!doctype>
<html>
<head>
<meta charset='utf-8'>
<title>我的網頁</title>
</head>
<body>
<h1>一級標題</h1>
<h2>二級標題</h2>
<p>一個<span>段落</span></p>
</body>
</html>
如果畫成樹形結構的話應該是這個樣子的
我們把它這些樹的節點替換成Node物件,按照規定整個文件對應的是Document物件,所有的標籤元素(包括HTML標籤)對應的是Element物件,而文字是Text物件,所以換成Node樹應該是這個樣子
所謂的DOM樹,就是這樣的一棵樹。通過一定的規則把html文件變成樹形結構,方便我們使用js來對其進行一些操作。Node裡邊存的東西在DOM標準裡有規定。其中不論是Document還是Element或者是Text都屬於Node節點。這就不得不提到nodeType了。
nodeType是Node物件的一個屬性,表示該節點的型別。節點的型別包括有上邊提到的Document、Element、Text以及表示註釋的Comment(也因此html註釋是可以從控制檯獲取到的),描述文件型別的DocumentType,表示沒有父級檔案的最小文件物件(輕量版的Document)DocumentFragment,以及其它不重要的。其中DocumentFragment優化是面試的一個考點…
這些節點的值在記憶體中用數字表示,1代表Element,3代表Text,9代表Document…至於為什麼,因為以前很窮,記憶體不夠約定來湊。那時候的程式設計師們約定好了上述數字對應的意義,然後一直流傳至今。當然,除了用1來表示Element,它還為你準備了一個常量Node.ELEMENT_NODE,同樣用來表示Element。你在控制檯輸入Node.ELEMENT_NODE,得到的結果是1。就像你在控制檯輸入Math.Pi,得到的結果是3.141592653一樣。同樣的,Node.TEXT_NODE結果是3,表示的是text。
Node屬性
鑑於屬性還挺多的,所以讓我們先來記一些簡單的單詞吧!
1. child/children/parent
2. node
3. first/last
4. next/previous
5. sibling/siblings
6. type
7. value/text/content
8. inner/outer
9. element
所有的屬性,都是這些單詞的組合。
比如childNodes,firstChild,lastChild,previousSibling,nextSibling,parentElement,parentNode,nodeName,nodeType,nodeValue,ownerDocument(獲取擁有這個節點的文件,一般是頁面的document節點),innerText,textContent…
DOM的主要功能是增刪改查,對於屬性這一塊,最多的還是查詢,找到這個元素,然後我們才可以修改它。
獲取所有子節點:childNodes(獲取子節點,包括Text等)
獲取所有子元素:children(獲取子標籤,不包括Text等)
獲取第一個兒子:firstChild
獲取第一個子元素:firstElementChild
獲取最後一個兒子:lastChild
獲取自己的兄弟(哥哥):previousSibling
獲取哥哥元素:previousElementSibling
獲取自己的兄弟(弟弟):nextSibling
獲取自己的父親:parentElement、parentNode。(我們都知道Element是Node的一個子集,表示的是html文件裡邊所有的標籤元素,所以這兩個方法顧名思義一個的意思是找到自己的標籤父親,另一個是隻要找到父親就可以了不論它是標籤還是別的什麼東西。鑑於在html裡除了標籤外基本上也沒什麼能作為父親所以這兩種方法沒什麼區別。)
獲取節點名稱:nodeName。除svg外所有標籤都是大寫,比如BODY....
獲取節點型別:nodeType。用數字表示,前邊說過了。
獲取節點值:nodeValue。對於Text,Comment節點,nodeValue返回節點的文字內容。對於Element節點,nodeValue返回null。
獲取內部文字:innerText、textContent。微軟引入了innerText,火狐和谷歌等引入了textContext,兩者主要功能都是獲取節點內部的文字,但是有一些不同。innerText能智慧識別css並將其解析,不會返回script標籤裡邊的原始碼,不會返回隱藏元素的文字,而textContent會返回所有元素的內容。也由於innerText解析css,所以會觸發重排,因此效能比較低一點。textContent會保留空行空格和換行符,innerText只會保留換行符。
Node方法
新增子節點:
Node.appendChild()
Node.insertBefore(),在參考節點之前插入新的節點,如果新的節點已經在DOM樹中,那麼會先被移除然後再新增。
Node.cloneNode(),克隆子節點。需要注意的是這裡有一個引數deep,如果傳入的是true那麼就是深拷貝,克隆本身以及它的內容(包括所有後代結點)。預設是false,只克隆結點本身(包括屬性、標籤名)。
判斷是否有子節點:Node.hasChildNodes()。文字節點同樣算是子節點。
判斷傳入的節點是不是該節點的後代節點:Node.contains( otherNode )
刪除子節點:Node.removeChild()。需要知道的是remove之後這個子節點仍然存在於記憶體當中,只是不顯示在頁面裡。
替換子節點:Node.replaceChild()。
判斷兩個節點是否相等:
Node.isEqualNode()
Node.isSameNode()
兩者的區別在於equal的話是隻要看起來相同即可,same指的是同一個。`div1 === div2`和`div1.isSameNode(div2)`結果相同。
常規化:Node.normalize()。通俗的解釋就是如果你用js在一個標籤裡邊生成了兩個text節點,使用該方法後會把兩個text節點合併為一個,使DOM樹看起來更簡潔。
Document
document介面是文件特有的介面,window.document所符合的API就是document介面。
Document屬性
innerText
不管你寫什麼都直接顯示。但是innerHTML
的話你寫的html程式碼(包括js部分)可以執行。所以最好不要用innerHTML因為它會把使用者的程式碼當做開發者的程式碼,不夠安全。
activeElement
,返回當前正在操作的元素。
domain
,獲取域名
head
,獲取head元素
hidden
,文件是否是隱藏的
images
,獲取所有的image元素
links
,獲取a標籤。anchors只能獲取到有name的a標籤
onXXXXX
,一系列的事件監聽
plugins
,看使用者是否開啟了外掛
readyState
,看是否載入完成
referrer
,檢視頁面的引薦者。可以通過這個屬性來拒絕為其它的訪問者提供服務。如果不是直接從位址列輸入網址進行訪問而是在當前頁面1點選跳轉至頁面2,那麼頁面2的referrer就是頁面1。在開發者工具的network裡邊檢視頁面的請求可以看見referrer屬性的值。
Document方法
close()
,關閉文件。一般說來在頁面載入完之後會自動關閉。在頁面開始載入的時候document就open了,然後往頁面裡邊寫東西,載入完之後頁面關閉。此時如果你再次open頁面,頁面裡原有的東西就不存在了,重新寫入,然後再次close。所以我們一般不用document.write()來往文件裡邊寫內容,因為一旦出現延時或者是非同步操作極容易清空頁面裡原有的東西。比如
document.write('hello')
setTimeout(()=>document.write('world'), 1000)
得到的結果是world,因為頁面重寫了。
execCommand()
,執行命令。比如execCommand(‘copy’),執行拷貝命令,拷貝你選中的內容到剪下板。在你想要寫一個富文字編輯器(帶有樣式的文字編輯器)的時候可能會用到這個API。
querySelectorAll()
返回的是一個偽陣列,querySelector()返回的是查詢到的第一個選擇器。
querySelectorAll()
返回的是一個靜態集合,DOM內部的變化並不會反映在該方法的返回結果中。parent.childNodes
是動態集合,DOM樹刪除或者新增一個相關節點都會立刻反映在NodeList介面中。
HTMLCollection VS NodeList
HTMLCollection
例項物件只能是Element節點,可以用id屬性或者name屬性來引用節點元素。
NodeList
例項物件可以包含其它節點,並且只能用數字索引來引用節點元素。