《DOM 啓蒙》讀書筆記及測試代碼
- 節點概覽
- 節點組成的樹形層次結構
- 節點類型
3.節點繼承 - 繼承而來節點打交道的屬性和方法
- 節點類型名稱和值
Node.prototype.nodeType
Node.prototype.nodeName
Node.prototype.nodeValue
- 創建節點
document.createElement
document.createTextNode
document.createComment
document.createAttribute
document.createDocumentFragment
- 字符串和節點的轉換
Element.prototype.innerHTML
Element.prototype.outerHTML
Node.prototype.textContent
Element.prototype.insertAdjacentElement
Element.prototype.insertAdjacentText
Element.prototype.insertAdjacentHTML
HTMLElement.prototype.innerText
HTMLElement.prototype.outerText
- 插入節點
Node.prototype.insertBefore
Node.prototype.appendChild
Element.prototype.before
Element.prototype.after
Element.prototype.append
Element.prototype.prepend
- 移除替換節點
Node.prototype.removeChild
Node.prototype.replaceChild
Element.prototype.remove
Element.prototype.replace
- 克隆節點
Node.prototype.cloneNode
- NodeList&HTMLCollection
length
屬性,因此可以是類數組對象- 實時反映
- 默認情況下,順序與樹中的順序一致
- 遍歷
- 節點(包括了註釋、文本節點)
Node.prototype.parentNode
Node.prototype.firstNode
Node.prototype.lastNode
Node.prototype.nextSibling
Node.prototype.perviosSibling
- 元素(IE 9 才支持,因此 jQuery 利用上面的節點遍歷相關屬性模擬了下面的屬性)
Element.prototype.fristElementChild
Element.prototype.lastElementChild
Element.prototype.nextElementChild
Element.prototype.perviosElementChild
Element.prototype.children
Element.prototype.parentElement
Element.prototype.previousElementSibling
Element.prototype.nextElementSibling
Element.prototype.childElementCount
- 節點(包括了註釋、文本節點)
- 驗證節點位置
Node.prototype.contains
Node.prototype.compareDocumentPosition
- 比較節點
Node.prototype.isEqualNode
Node.prototype.isSameNode
- 文檔節點
Object
<-Node
<-Document
<-HTMLDocument
- 屬性和方法
- 通用信息
title
URL
charset
contentType
compatMode
BackCompat(怪異模式)CSS1Compat(嚴格模式)referrer
lastModified
- 等等
- 快捷訪問
doctype
:現代瀏覽器不在document.childNodes
中head
body
documentElement
:即<html lang="en">
- 探測特性
implementation.hasFeature
- 獲取激活節點
- 是否聚焦在當前文檔窗口上
- 獲取全局對象
- 獲取
document
- 元素節點
HTML*Element
- 創建元素,上面的
document.createElement
- 標籤名
Node.prototype.nodeName
Element.prototype.tagName
- 屬性集合
- 操作屬性
Element.prototype.getAttribute
Element.prototype.setAttribute
Element.prototype.hasAttribute
Element.prototype.removeAttribute
Element.prototype.getAttributeNS
Element.prototype.setAttributeNS
Element.prototype.hasAttributeNS
Element.prototype.removeAttributeNS
Element.prototype.getAttributeNode
Element.prototype.getAttributeNodeNS
Element.prototype.setAttributeNode
Element.prototype.setAttributeNodeNS
Element.prototype.removeAttributeNode
- 類操作
Element.prototype.className
Element.prototype.classList
add
remove
toggle
contains
data-*
屬性HTMLElement.prototype.dataset
- 選取元素節點
- 特定元素
Element.prototype.querySelector
和document.querySelector
document.getElementById
- 節點列表
Element.prototype.querySelectorAll
和document.querySelectorAll
非實時的,下面三個是實時的。目前遇到的第一個非實時的獲取方法。Element.prototype.getElementsByTagName
和document.getElementsByTagName
Element.prototype.getElementsByTagNameNS
和document.getElementsByTagNameNS
Element.prototype.getElementsByClassName
和document.getElementsByClassName
document.getElementsByName
- 子元素
Element.prototype.children
實時、有序
- 預定義的節點列表
document.images
document.embeds
document.plugins
document.links
document.forms
document.scripts
document.anchors
document.applets
document.children
document.styleSheets
- 驗證選取的元素
Element.prototype.matchesSelector
針對不同瀏覽器加前綴Element.prototype.webkitMatchesSelector
Element.prototype.mozMatchesSelector
Element.prototype.msMatchesSelector
Element.prototype.oMatchesSelector
Element.prototype.matches
新的這個,不用加前綴
- 元素節點幾何量與滾動幾何量
- CSSOM 視圖模塊規範中定義了訪問和操作元素節點可視化表象的元素幾何量、滾動幾何量的屬性和方法。
- 相對
HTMLElement.prototype.offsetParent
的位置 HTMLElement.prototype.offsetLeft
相對於自身offsetParent
HTMLElement.prototype.offsetTop
相對於offsetParent
Element.prototype.clientTop
相對於自身邊框Element.prototype.clientLeft
相對於自身邊框Element.prototype.scrollTop
滾動元素Element.prototype.scrollLeft
滾動元素- 相對視區的偏移
Element.prototype.getBoundingClientRect
Element.prototype.getClientRects
- 元素在視圖中的尺寸
HTMLElement.prototype.offsetHeight
包括邊框HTMLElement.prototype.offsetWidth
包括邊框Element.prototype.getBoundingClientRect().width
包括邊框Element.prototype.getBoundingClientRect().height
包括邊框Element.prototype.clientWidth
不包括邊框Element.prototype.clientHeight
不包括邊框Element.prototype.scrollWidth
滾動元素Element.prototype.scrollHeight
滾動元素- 徹底弄清楚幾個寬高
- 特定點上最頂層元素
document.elementFromPoint
- 滾動元素到視區
Element.prototype.scrollIntoView
Element.prototype.scrollIntoViewIfNeeded
- 元素節點內聯樣式
- 獲取內聯樣式
HTMLElement.prototype.style
得到CSSStyleDeclaration
- 設置內聯樣式
- 直接通過
style
獲得、設置、刪除內聯樣式屬性 style.setProperty
style.getPropertyValue
style.removeProperty
- 直接通過
- 所有內聯樣式
style.cssText
Element.prototype.setAttribute
、Element.prototype.getAttribute
、Element.prototype.removeAttribute
- 計算樣式
window.getComputedStyle
上面獲得樣式都是內聯,不疊加計算的,這個方法返回的是疊加計算後的實際值。window.getComputedStyle
得到的CSSStyleDeclaration
是隻讀的。
- 文本節點
Object
<-Node
<-CharacterData
<-Text
和元素混在一區的文本會轉換爲文本節點- 文本節點屬性和方法
- 創建節點
- 字符(包括空白符和回車符)會創建文本節點
- 編程式創建:
document.createTextNode
- 節點值
Node.prototype.nodeValue
Node.prototype.textContent
會合並所有子文本節點CharacterData.prototype.data
Text.wholeText
- 操作文本節點
CharacterData.prototype.appendData
CharacterData.prototype.deleteData
CharacterData.prototype.insertData
CharacterData.prototype.replaceData
CharacterData.prototype.substringData
Comment
也繼承了CharacterData
,所以也擁有這些方法
- 多個兄弟文本節點
- 拿上面的例子來說,
strong
元素把文本截斷,所以得到的childNodes
的length
爲 3。 - 另外也可以編程式地添加兩個文本節點,而不會合並。
Node.prototype.normalize
合併兄弟文本節點。Text.prototype.splitText
分割文本節點
- 拿上面的例子來說,
Node.prototype.textContent
- 合併返回所有子文本的內容
- 設置的時候會移除所有子節點,替換爲新的
Text
節點 HTMLElement.prototype.innerText
區別:innerText
認識 Css,忽略隱藏文本。innerText
關心 Css 觸發重排。innerText
使文本規範化。innerText
非標準,新的火狐好像也支持了。
DocumentFragment
節點(文檔片段)- 空的文檔模板,行爲與實時 DOM 樹相似,但是僅在內存中存在。
- 創建文檔片段節點
document.createDocumentFragment
- 與直接創建 div,然後創建 DOM 結構的區別:
- 文檔片段可以包含任意節點(body、html 除外)。
- 文檔片段插入 DOM 中時,自身不會添加,只插入子節點。
- 文檔片段插入 DOM 中時實際上是把傳輸的內容放到了 DOM,自身的內容就沒了。
- 在內存中創建節點注入到實時節點結構是極其高效的。
- 文檔片段沒有
innerHTML
屬性,變通方法是新建一個 div,利用 div 的innerHTML
。 - 通過
Node.prototype.cloneNode
將文檔片段保存在內存中。 - Css 樣式表和 Css 規則
- 樣式概述
- 元素內聯樣式
HTMLLinkElement
外部樣式類HTMLStyleElement
頁面內聯樣式類CSSStyleSheet
樣式表對象類CSSStyleRule
樣式規則類
- 創建樣式
document.createElement('style')
document.createElement('link')
- 獲取所有樣式表
document.styleSheets
(包括外部和內部)- 實時、
length
屬性、類數組對象。 - 單個樣式表用
sheet
屬性從HTMLLinkElement
或HTMLStyleElement
獲取
CSSStyleSheet
的屬性和方法CSSStyleRule
的屬性和方法- 修改樣式規則
CSSStyleSheet
的insertRule
、deleteRule
、addRule
、removeRule
方法。- 直接通過
CSSStyleRule.prototype.style
進行修改。
CSSStyleSheet.prototype.disabled
使樣式表失效。- DOM 中的 JavaScript
- 腳本概述
- 元素內聯腳本,
<a href="javascript:void(0)"></a>
和<button onclick="alert('yo')"></button>
等。 HTMLScriptElement
頁面內聯腳本。HTMLScriptElement
外部腳本。- 腳本元素內會新建一個文本節點,可以通過
innerHTML
、textContent
、innerText
來獲取值。
- 元素內聯腳本,
- 同步加載和解析
- 如果加載和解析是異步的,那麼
document.write
輸出的位置根本無法確定,而如果在onload
事件之後調用document.write
會自動觸發document.open
清空頁面,因此 Js 默認採用了同步地加載方式,它會阻塞頁面的解析。現代瀏覽器是支持併發下載腳本的。 - 頁面內聯腳本也是如此,會同步執行,阻塞頁面解析。
- 因此在同步加載的情況下,把 Js 腳本放到頁面底部是比較好的策略。
- 如果加載和解析是異步的,那麼
- 異步加載腳本
- 首先異步加載的腳本中出現,
document.write
會報錯。 defer
異步加載、在DOMContentLoaded
事件之前有序執行。低版本的 IE 支持。async
異步加載,加載完就執行,不利於依賴管理。IE 10 才支持,優先級高於defer
。- 手動創建
script
標籤實現異步加載(前端模塊加載器如:seajs、requirejs 使用的都是這種方式)。
- 首先異步加載的腳本中出現,
onload
和onreadystatechange
- 通常我們會爲手動創建的
script
標籤綁定一個加載完成的回調,在之後做一些操作,比如 seajs 會在加載完以後把script
元素及其事件刪除,防止內存泄漏,因爲 seajs 已經把腳本的內容保存在模塊對象上,供延遲調用了。 - 而對於 IE 8 及以下的瀏覽器,
Node
不支持onload
事件,所以使用onreadystatechange
來代替。
- 通常我們會爲手動創建的
- 獲取當前執行的腳本
document.currentScript
- IE 6-9 下沒有這個屬性,兼容 IE 的方案。
- 獲取所有腳本
document.scripts
- DOM 事件
- 三種添加事件監聽方式
- 行內屬性事件:
<div onclick="alert('click')"></div>
- 屬性事件:
mdiv.onclick = () => alert('click')
addEventListener
:mdiv.addEventListener('click',() => alert('click'), false)
(回調函數的this
自動綁定到該元素,並且支持綁定多個回調)- IE
attachEvent
不支持捕獲階段。
- 行內屬性事件:
- 事件類型
UIEvent
load
、onload
、abort
、error
資源加載相關resize
、scroll
窗口尺寸相關context menu
右鍵菜單
FocusEvent
blur
、focus
、focusin
、focusout
FormEvent
change
、reset
、submit
、select
MouseEvent
click
、dbclick
mousedown
、mouseup
mouseenter
、mouseout
不冒泡mouseleave
、mouseover
冒泡mousemove
WheelEvent
- 瀏覽器裏用的是
mousewheel
規範用的是wheel
- 瀏覽器裏用的是
KeyboardEvent
keydown
、keyup
、keypress
TouchEvent
touchstart
、touchend
touchmove
、touchcancel
touchenter
、touchleave
- 拖拽相關
drag
、dragover
、drop
dragstart
、dragend
dragenter
、dragleave
- 文檔相關
readystatechange
DOMContentLoaded
- 其它
afterprint
、beforeprint
beforeupload
hashchange
message
offline
、online
pagehide
、pageshow
- 移除事件監聽
removeEventListener
只支持通過函數引用添加的事件監聽函數。- IE
detachEvent
。
- 事件捕獲和冒泡
addEventListener
第三個參數爲true
則在捕獲階段觸發、false
則在冒泡階段觸發,默認是false
。- 其他兩種事件綁定都是在冒泡時觸發的。
- IE
attachEvent
不支持捕獲階段,也沒有第三個參數,都是在冒泡階段觸發。
- 常見事件對象屬性
target
和currentTarget
,currentTarget
是當前活動對象,target
是目標對象,只有在目標階段,兩者纔是相等的。- 五個座標,見徹底弄清楚幾個寬高 。
stopPropagation
:因爲事件可以在各層級的節點中傳遞, 不管是冒泡還是捕獲, 有時我們希望事件在特定節點執行完之後不再傳遞, 可以使用事件對象的stopPropagation
方法。preventDefault
:元素上帶有的功能. 如: 點擊 a 鏈接節點的跳轉動作, 點擊 submit 按鈕表單會提交等,如果監聽這些元素的事件時不希望執行默認動作,就可以使用preventDefault
方法。return false
:退出執行, return false 之後的所有觸發事件和動作都不會被執行。有時候return false
可以用來替代stopPropagation
和preventDefault
,除此之外,還可以返回對象, 跳出循環等。stopImmediatePropagation
:和stopPropagation
區別是這個方法會把綁定在同一個元素的剩下的回調都取消。eventPhase
屬性,0 表示不在事件中,1 表示捕捉階段、2 表示目標階段、3 表示冒泡階段。- 需要注意的是
event
是實時的,也就是說在console
輸出的event
已經不是當時的那個event
了。
- 自定義事件
document.createEvent
initCustomEvent(event,bubble?,cancelable?,event.detail)
fireEvent
(IE) 和dispatchEvent
- IE9 裏
initCustomEvent
需要第四個參數。 - DOM4 裏面添加了
CustomEvent
。
- 模擬出發鼠標事件
- 類似
jQuery.trigger()
方法。 - 藉助
initMouseEvent
來實現。
- 類似
- 事件委託
- 事件委託是藉助事件冒泡機制,用父級元素來統一管理子級的相同事件。
- 原理是不管是哪個子級觸發的相同事件,都可以通過
event.target
拿到這個子級元素,然後對其做相應的操作,因爲操作邏輯是一樣的,因此可以在父級中複用邏輯。 - 在處理
click
、mousedown
、mouseup
、keydown
、keyup
、keypress
等事件時十分有效。 - 可以有效的減少綁定,降低內存消耗。