概念
文檔對象模型(Document Object Model,簡稱 DOM),是 W3C 組織推薦的處理可擴(kuò)展標(biāo)記語言的標(biāo)準(zhǔn)編程接口。它是一種與平臺和語言無關(guān)的應(yīng)用程序接口(API),它可以動態(tài)地 訪問程序和腳本,更新其內(nèi)容、結(jié)構(gòu)和 www 文檔的風(fēng)格(目前,HTML 和 XML 文檔是通過 說明部分定義的)。文檔可以進(jìn)一步被處理,處理的結(jié)果可以加入到當(dāng)前的頁面。DOM 是一 種基于樹的 API 文檔,它要求在處理過程中整個文檔都表示在存儲器中。
DOM 樹
DOM 又稱為文檔樹模型。文檔:一個網(wǎng)頁可以稱為文檔。節(jié)點:網(wǎng)頁中的所有內(nèi)容都是節(jié)點 (標(biāo)簽、屬性、文本、注釋等),元素:網(wǎng)頁中的標(biāo)簽,屬性:標(biāo)簽的屬性。

獲取頁面元素
我們想要操作頁面上的某部分(顯示/隱藏,動畫),需要先獲取到該部分對應(yīng)的元素,才能進(jìn)行后續(xù)操作。
1.根據(jù) id 獲取元素
- 方法:調(diào)用 document 對象的
getElementById方法。 - 參數(shù):字符串類型的 id 的屬性值。
- 返回值:對應(yīng) id 名的元素對象。
注意1:由于 id 名具有唯一性,部分瀏覽器支持直接使用 id 名訪問元素,但不是標(biāo)準(zhǔn)方式, 不推薦使用。
注意2:代碼執(zhí)行順序,如果 js 在 html 結(jié)構(gòu)之前,會導(dǎo)致結(jié)構(gòu)未加載,不能獲取對應(yīng)id的元素。
2.根據(jù)標(biāo)簽名獲取元素
- 方法:調(diào)用 document 對象的
getElementsByTagName方法。 - 參數(shù):字符串類型的標(biāo)簽名。
- 返回值:同名的元素對象組成的數(shù)組。
注意1:操作數(shù)據(jù)時需要按照操作數(shù)組的方法進(jìn)行。
注意2:getElementsByTagName 方法內(nèi)部獲取的元素是動態(tài)增加的,在HTML結(jié)構(gòu)之前使用會生成空數(shù)組,并在結(jié)構(gòu)加載過程中動態(tài)增加對應(yīng)的元素。
元素對象內(nèi)部獲取標(biāo)簽元素:獲取的元素對象內(nèi)部,本身也可以調(diào)用根據(jù)標(biāo)簽獲取元素方法,例如 div 元素對象也可以調(diào)用 getElementsByTagName 方法。目的是縮小選擇元素的范圍,類似 css 中的后代選擇器。
3.根據(jù) name 獲取元素
- 方法:調(diào)用 document 對象的 getElementsByName 方法。
- 參數(shù):字符串類型的 name 屬性值。
- 返回值:name 屬性值相同的元素對象組成的數(shù)組。
不建議使用:也是動態(tài)獲取元素,在 IE 和 Opera 中有兼容問題,會多選中 id 屬性值相同的元素。
4.根據(jù)類名獲取元素
- 方法:調(diào)用 document 對象的
getElementsByClassName方法。 - 參數(shù):字符串類型的 class 屬性值。
- 返回值:class 屬性值相同的元素對象組成的數(shù)組。
瀏覽器兼容問題:也是動態(tài)獲取元素,并且不支持 IE8 及以下的瀏覽器
5.根據(jù)選擇器獲取元素
- 方法1:調(diào)用 document 對象的 querySelector 方法,通過 css 中的選擇器去選取第一個 符合條件的標(biāo)簽元素。
document.querySelector("#id .class") - 方法2:調(diào)用 document 對象的 querySelectorAll 方法,通過 css 中的選擇器去選取所 有符合條件的標(biāo)簽元素。
- 參數(shù):字符串類型的 css 中的選擇器。
瀏覽器兼容問題:在 html 結(jié)構(gòu)之前,會導(dǎo)致結(jié)構(gòu)未加載,不能獲取對應(yīng)的元素,并且不支持 IE8 以下的瀏覽器。
事件
事件:在什么時候做什么事。執(zhí)行機(jī)制:觸發(fā)--響應(yīng)機(jī)制。
綁定事件(注冊事件)三要素:
1、事件源:給誰綁定事件;
2、事件類型:綁定什么類型的事件,如:click 單擊;
3、事件函數(shù):事件發(fā)生后執(zhí)行什么內(nèi)容,寫在函數(shù)內(nèi)部。
事件監(jiān)聽:JavaScript 解析器會給有綁定事件的元素添加一個監(jiān)聽,解析器會一直監(jiān)測這個元素,只要觸發(fā)對應(yīng)的綁定事件,會立刻執(zhí)行事件函數(shù)。
常用事件監(jiān)聽方法:
- 綁定 HTML 元素屬性
<input type="button" id="btn" value="點擊有驚喜" onclick="alert('點我做什么?')">
- 綁定 DOM 對象屬性
<input type="button" id="btn" value="點擊有驚喜">
<script>
// 獲取元素
var btn = document.getElementById("btn");
// 添加綁定事件
btn.onclick = function () {
// 定義的是事件被觸發(fā)后要做的事情
alert("點我干嘛?");
};
</script>
常用的鼠標(biāo)事件類型:
| 類型 | 說明 |
|---|---|
| onclick | 鼠標(biāo)左鍵單擊觸發(fā) |
| ondbclick | 鼠標(biāo)左鍵雙擊觸發(fā) |
| onmousedown | 鼠標(biāo)按鍵按下觸發(fā) |
| onmouseup | 鼠標(biāo)按鍵放開時觸發(fā) |
| onmousemove | 鼠標(biāo)在元素上移動觸發(fā) |
| onmouseover | 鼠標(biāo)移動到元素上觸發(fā) |
| onmouseout | 鼠標(biāo)移出元素邊界觸發(fā) |
元素屬性操作
非表單元素屬性
例如:href、title、id、src 等。
調(diào)用方式:元素對象打點調(diào)用屬性名,例如 obj.href。
注意:部分的屬性名跟關(guān)鍵字和保留字沖突,會更換寫法。
class → className
for → htmlFor
rowspan → rowSpan
屬性賦值:給元素屬性賦值,等號右側(cè)的賦值都是字符串格式。
獲取標(biāo)簽內(nèi)部內(nèi)容屬性
獲取標(biāo)簽內(nèi)部內(nèi)容的屬性有兩個:innerHTML 和 innerText
-
innerHTML屬性,在獲取標(biāo)簽內(nèi)部內(nèi)容時,如果包含標(biāo)簽,獲取的內(nèi)容會包含標(biāo)簽,包括空白換行等。 -
innerText屬性,在獲取標(biāo)簽內(nèi)部內(nèi)容時,如果包含標(biāo)簽,獲取的內(nèi)容會過濾標(biāo)簽,并且會去掉換行和縮進(jìn)等空白。
還可以通過兩個屬性給雙標(biāo)簽內(nèi)部去更改內(nèi)容:
-
innerHTML設(shè)置屬性值,有標(biāo)簽的字符串,會按照 HTML 語法中的標(biāo)簽加載。 -
innerText設(shè)置屬性值,有標(biāo)簽的字符串,會按照普通的字符加載。
對比使用場景:
-
innerText:在設(shè)置純字符串時使用。 -
innerHTML:在設(shè)置有內(nèi)部子標(biāo)簽結(jié)構(gòu)時使用。
表單元素屬性
- value 用于大部分表單元素的內(nèi)容獲取(option除外)
- type 可以獲取input標(biāo)簽的類型(輸入框或復(fù)選框等)
- disabled 禁用屬性
- checked 復(fù)選框選中屬性
- selected 下拉菜單選中屬性
注意:在 DOM 中元素對象的屬性值只有一個時,會被轉(zhuǎn)成布爾值顯示。 例如:txt.disabled = true;
自定義屬性操作
- getAttribute(name) 獲取標(biāo)簽行內(nèi)屬性
- setAttribute(name,value) 設(shè)置標(biāo)簽行內(nèi)屬性
- removeAttribute(name) 移除標(biāo)簽行內(nèi)屬性
與element.屬性的區(qū)別: 上述三個方法用于獲取任意的行內(nèi)屬性,包括自定義的屬性。
注意:上述方法獲取屬性是通過字符串進(jìn)行匹配,因此或者自有屬性是不需要修改屬性名。例如:getAttribute("class")
style 樣式屬性操作
- 使用 style 屬性方式設(shè)置的樣式顯示在標(biāo)簽行內(nèi)。
- element.style 屬性的值,是所有行內(nèi)樣式組成的一個樣式對象。
- 樣式對象可以繼續(xù)點語法調(diào)用或更改 css 的行內(nèi)樣式屬性,例如 width、height 等屬性。
注意1:類似 background-color 這種復(fù)合屬性的單一屬性寫法,是由多個單詞組成的,要修改為駝峰命名方式書寫 backgroundColor。
注意2:通過樣式屬性設(shè)置寬高、位置的屬性類型是字符串,需要加上 px 等單位。
className 類名屬性操作
修改元素的 className 屬性相當(dāng)于直接修改標(biāo)簽的類名。如果需要修改多條 css 樣式,可以提前將修改后的樣式設(shè)置到一個類選擇器中,后續(xù)通過修改類名的方式,批量修改 css 樣式。
在實際工作中,如果需要設(shè)置的屬性值較多時,推薦使用 className 類名屬性操作,如果需要設(shè)置或者修改的屬性只有一兩條,那么推薦使用style樣式屬性操作。
節(jié)點操作
節(jié)點屬性
nodeType 節(jié)點的類型,屬性值為數(shù)字,表示不同的節(jié)點類型,共 12 種,只讀。
1:元素節(jié)點;2: 屬性節(jié)點; 3: 文本節(jié)點。
nodeName 節(jié)點的名稱(標(biāo)簽名稱),只讀。
nodeValue 節(jié)點值,返回或設(shè)置當(dāng)前節(jié)點的值,元素節(jié)點的 nodeValue 始終是 null。
父子節(jié)點常用屬性
| 屬性名 | 說明 |
|---|---|
| childNodes | 只讀屬性,獲取一個節(jié)點所有子節(jié)點的實時的集合,集合是動態(tài)變化的。 |
| children | 只讀屬性,返回一個節(jié)點所有的子元素節(jié)點集合,是一個動態(tài)更新的 HTML 元素集合。 |
| firstChild | 只讀屬性,返回該節(jié)點的第一個子節(jié)點,如果該節(jié)點沒有子節(jié)點則返回 null。 |
| lastChild | 只讀屬性,返回該節(jié)點的最后一個子節(jié)點,如果該節(jié)點沒有子節(jié)點則返回 null。 |
| parentNode | 返回一個當(dāng)前節(jié)點的父節(jié)點,如果沒有這樣的節(jié)點,比如說像這個節(jié)點是樹結(jié)構(gòu)的頂端或者沒有插入一棵樹中,這個屬性返回 null。 |
| parentElement | 返回當(dāng)前節(jié)點的父元素節(jié)點,如果該元素沒有父節(jié)點,或者父節(jié)點不是一個 DOM 元素,則返回 null。 |
兄弟節(jié)點常用屬性
| 屬性名 | 說明 |
|---|---|
| nextSibling | 只讀屬性,返回與該節(jié)點同級的下一個節(jié)點,如果沒有返回null。 |
| previousSibling | 只讀屬性,返回與該節(jié)點同級的上一個節(jié)點,如果沒有返回null。 |
| nextElementSibling | 只讀屬性,返回與該節(jié)點同級的下一個元素節(jié)點,如果沒有返回null。 |
| previousElementSibling | 只讀屬性,返回與該節(jié)點同級的上一個元素節(jié)點,如果沒有返回null。 |
注意:nextElementSibling 和 previousElementSibling 有兼容性問題,IE9以后才支持。
常用節(jié)點操作方法
創(chuàng)建節(jié)點:
- document.createElement("div") 創(chuàng)建元素節(jié)點
- document.createAttribute("id") 創(chuàng)建屬性節(jié)點
- document.createTextNode("hello") 創(chuàng)建文本節(jié)點
一般將創(chuàng)建的新節(jié)點存在變量中,方便使用。
添加、替換、插入、刪除:
- parentNode.appendChild(child):將一個節(jié)點添加到指定父節(jié)點的子節(jié)點列表末尾。
- parentNode.replaceChild(newChild, oldChild):用指定的節(jié)點替換當(dāng)前節(jié)點的一個子節(jié)點,并返回被替換掉的節(jié)點。
- parentNode.insertBefore(newNode, referenceNode):在參考節(jié)點之前插入一個擁有指定父節(jié)點的子節(jié)點,referenceNode 必須設(shè)置,如果 referenceElement 為 null 則 newNode 將被插入到子節(jié)點的末尾。
- parentNode.removeChild(child):移除當(dāng)前節(jié)點的一個子節(jié)點。這個子節(jié)點必須存在于當(dāng)前節(jié)點中。
克?。?/strong>
- Node.cloneNode():克隆一個節(jié)點,并且可以選擇是否克隆這個節(jié)點下的所有內(nèi)容。參數(shù)為 Boolean 布爾值,表示是否采用深度克隆,如果為 true,則該節(jié)點的所有后代節(jié)點也都會被克隆,如果為 false,則只克隆該節(jié)點本身,默認(rèn)值為 true,節(jié)點下的內(nèi)容會被克隆。
注意:克隆時,標(biāo)簽上的屬性和屬性值也會被復(fù)制,寫在標(biāo)簽行內(nèi)的綁定事件可以被復(fù)制, 但是通過JavaScript 動態(tài)綁定的事件不會被復(fù)制。
判斷方法:
- Node.hasChildNodes():沒有參數(shù),返回一個 Boolean 布爾值,來表示該元素是否包含有 子節(jié)點。
- Node.contains(child):返回一個 Boolean 布爾值,來表示傳入的節(jié)點是否為該節(jié)點的后 代節(jié)點
有三種方法可以判斷當(dāng)前節(jié)點是否有子節(jié)點。
- node.firstChild !== null
- node.childNodes.length > 0
- node.hasChildNodes()
事件操作
注冊事件的其他方法
- element.addEventListener() 方法。
參數(shù):
第一個參數(shù):事件類型的字符串(onclick事件直接書寫”click”,不需要加 on)
第二個參數(shù):事件函數(shù)
同一個元素可以多次綁定事件監(jiān)聽,同一個事件類型可以注冊多個事件函數(shù)
兼容性問題:不支持 IE9 以下的瀏覽器 - element.attachEvent() 方法。
參數(shù):
第一個參數(shù):事件類型的字符串(onclick事件需要加 on)
第二個參數(shù):事件函數(shù)
同一個元素可以多次綁定事件監(jiān)聽,同一個事件類型可以注冊多個事件函數(shù)
兼容性問題:只支持 IE10 及以下的瀏覽器,但是在 IE8 及以下的瀏覽器會出現(xiàn)事件隊列順序錯亂。 - 兼容寫法
自定義一個注冊事件函數(shù);
參數(shù):事件源,事件類型(不加 on),事件函數(shù)
IE9 及以上的瀏覽器,使用 addEventListener 方法
IE9 以下的瀏覽器,使用 attachEvent 方法
判斷瀏覽器時,不需要判斷它的版本,可以檢測瀏覽器能力(瀏覽器能力檢測:將某個方法的調(diào)用作為 if 語句的判斷條件,如果瀏覽器認(rèn)識該方法返回 true,否則返回false)
function addEvent(element,type,fun) {
// IE 9 及以上的瀏覽器和其他瀏覽器,使用 addEventListener 方法
// IE 9 以下的瀏覽器,使用 attachEvent 方法
// 瀏覽器能力檢測
if (element.addEventListener) {
element.addEventListener(type, fun);
} else if (ele.attachEvent) {
element.attachEvent("on" + type, fun);
}
}
解除事件綁定
- element.removeEventListener() 方法。
參數(shù):
第一個參數(shù):事件類型的字符串(直接書寫”click”,不需要加 on)
第二個參數(shù):事件函數(shù)引用名
注意:沒有辦法移除一個匿名函數(shù),所以在注冊事件時需要單獨聲明一個有函數(shù)名的事件函數(shù)。
兼容性問題:不支持 IE9 以下的瀏覽器 - element.detachEvent() 方法。
參數(shù):
第一個參數(shù):事件類型的字符串(需要加 on)
第二個參數(shù):事件函數(shù)
注意:沒有辦法移除一個匿名函數(shù),所以在注冊事件時需要單獨聲明一個有函數(shù)名的事件函數(shù)。
兼容性問題:只支持 IE10 及以下的瀏覽器 - 兼容寫法
自定義一個移除事件函數(shù)
參數(shù):事件源,事件類型(不加 on),事件函數(shù)
IE9 及以上的瀏覽器,使用 removeEventListener 方法
IE9 以下的瀏覽器,使用 detachEvent 方法
建議:將自己封裝的一些常用函數(shù)和方法,放到一個單獨的 .js 文件中。
function removeEvent(element,type,fun) {
// IE 9 及以上的瀏覽器和其他瀏覽器,使用 removeEventListener 方法
// IE 9 以下的瀏覽器,使用 detachEvent 方法
// 瀏覽器能力檢測
if (element.removeEventListener) {
element.removeEventListener(type, fun);
} else if (element.detachEvent) {
element.detachEvent("on" + type, fun);
}
}
事件流
祖先級與目標(biāo)元素之間綁定了相同的事件,觸發(fā)事件時程序有兩種可能的執(zhí)行方向。

事件流三個階段:第一個階段:事件捕獲;第二個階段:事件執(zhí)行過程;第三個階段:事件冒泡。
addEventListener() 第三個參數(shù)為 false 時,事件冒泡
addEventListener() 第三個參數(shù)為 true 時,事件捕獲
onclick 類型:只能進(jìn)行事件冒泡過程,沒有捕獲階段
attachEvent() 方法:只能進(jìn)行事件冒泡過程,沒有捕獲階段
事件委托:利用事件冒泡,將子級的事件委托給父級加載,同時,需要利用事件函數(shù)的一個 e 參數(shù),該參數(shù)內(nèi)部存儲的是事件對象,通過 e.target 屬性獲取真正觸發(fā)事件的事件源。
事件對象
只要觸發(fā)事件,就會有一個對象,內(nèi)部存儲了與事件相關(guān)的數(shù)據(jù)。
e 在低版本瀏覽器中有兼容問題,低版本瀏覽器使用的是 window.event
兼容寫法:e = e || window.event
事件對象常用的屬性:
| 屬性名 | 說明 |
|---|---|
| e.eventPhase | 查看事件觸發(fā)時所處的階段 |
| e.target | 用于獲取觸發(fā)事件的元素 |
| e.srcElement | 用于獲取觸發(fā)事件的元素,低版本瀏覽器使用 |
| e.currentTarget | 用于獲取綁定事件的事件源元素 |
| e.type | 獲取事件類型 |
| e.clientX / e.clientY | 所有瀏覽器都支持,鼠標(biāo)距離瀏覽器窗口左上角的距離 |
| e.pageX / e.pageY | IE8 以前不支持,鼠標(biāo)距離整個HTML頁面左上頂點的距離 |
| e.preventDefault() | 取消默認(rèn)行為 |
| e.returnValue = false | 取消默認(rèn)行為,低版本瀏覽器使用 |
| e.stopPropagation() | 阻止冒泡,標(biāo)準(zhǔn)方式 |
| e.cancelBubble = true | 阻止冒泡,IE 低版本,標(biāo)準(zhǔn)中已廢棄 |
其他事件類型可以參考【事件參考 | MDN (mozilla.org)】
特效制作相關(guān)屬性
偏移量屬性
| 屬性名 | 說明 |
|---|---|
| offsetParent | 偏移參考父級,距離自己最近的有定位的父級, 如果都沒有定位參考body(html) |
| offsetLeft / offsetTop | 偏移位置 |
| offsetWidth / offsetHeight | 偏移大小 |

客戶端大小
| 屬性名 | 說明 |
|---|---|
| client | 系列沒有參考父級元素。 |
| clientLeft / clientTop | 邊框區(qū)域尺寸,不常用 |
| clientWidth / clientHeight | 邊框內(nèi)部大小 |

滾動偏移屬性
| 屬性名 | 說明 |
|---|---|
| scrollLeft/scrollTop | 盒子內(nèi)部滾動出去的尺寸 |
| scrollWidth/scrollHeight | 盒子內(nèi)容的寬度和高度 |
