每天一句:成長的速度取決于在過程中發(fā)現(xiàn)和解決問題的速度,最終這是一個量變引發(fā)質(zhì)變的過程宝惰;
DOM(Document Object Model)即文檔對象模型,針對HTML和XML文檔的API(應(yīng)用程序接口)再沧。DOM描繪了一個層次化的節(jié)點樹掌测,用于添加、刪除和修改頁面的某一部分产园。
一汞斧、DOM介紹
DOM中的三個字母,D(文檔)可以理解為整個WEB加載的頁面文檔什燕;O(對象)可以理解為類似window對象子類的東西粘勒,可以調(diào)用屬性和方法,也就是document對象屎即;M(模型)可以理解為網(wǎng)頁文檔的樹形結(jié)構(gòu)庙睡。
DOM提供了訪問結(jié)構(gòu)化文檔的一種方式事富,但DOM并不是一種技術(shù),它只是訪問結(jié)構(gòu)化文檔(主要是XML文檔和HTML文檔)的一種思想乘陪。
DOM有三個等級统台,分別是DOM1、DOM2啡邑、DOM3贱勃,并且DOM1在1998年10月成為W3C標(biāo)準(zhǔn)。DOM1所支持的瀏覽器包括IE6+谤逼、Firefox贵扰、Safari、Chrome和Opera1.7+流部。
注: IE中的所有DOM對象都是以COM對象的形式實現(xiàn)的戚绕,即是IE中的DOM會與其他瀏覽器有一定的差異。
-
節(jié)點
加載HTML頁面時枝冀,web瀏覽器生成一個樹形結(jié)構(gòu)舞丛,用來表示頁面內(nèi)部結(jié)構(gòu)。DOM將這種樹形結(jié)構(gòu)理解為由節(jié)點組成:
節(jié)點樹
上圖樹形結(jié)構(gòu)果漾,html標(biāo)簽球切,沒有父輩,沒有兄弟跨晴,所以html標(biāo)簽為根標(biāo)簽欧聘。head標(biāo)簽是html的子標(biāo)簽片林,meta和title標(biāo)簽是兄弟關(guān)系端盆。如果把每個標(biāo)簽當(dāng)作一個節(jié)點,那么這些節(jié)點組合成的就是節(jié)點樹费封。
節(jié)點種類
元素節(jié)點焕妙、文本節(jié)點、屬性節(jié)點;
<div id="box">測試Div</div>
元素節(jié)點: div
屬性節(jié)點: id="box"
文本節(jié)點: 測試Div
二弓摘、查找元素
- getElementById() 獲取特定ID的節(jié)點
- getElementsByName() 通過name書信獲取到節(jié)點列表
- getElementsByTagName() 獲取相同元素的節(jié)點列表
- getElementsByClassName() 獲取特定類名元素的節(jié)點列表
案例: getElementsByClassName的封裝(低版本中沒有該方法)
案例: 導(dǎo)航下拉菜單效果
三焚鹊、DOM節(jié)點
- node節(jié)點屬性
節(jié)點可以分為元素節(jié)點、屬性節(jié)點和文本節(jié)點韧献,而這些節(jié)點又有三個非常有用的屬性: nodeName末患、nodeType和nodeValue;
var oBox = document.getElementById("box");
alert(oBox.nodeName); // DIV
alert(oBox.nodeType); // 1
alert(oBox.nodeValue); // null
var att = oBox.attributes; // 獲取所有屬性節(jié)點集合
alert(att[0].nodeValue); // box
- 層次節(jié)點屬性
節(jié)點的層次可以劃分為: 父節(jié)點與子節(jié)點、兄弟節(jié)點兩種锤窑。當(dāng)需要獲取其中一個元素節(jié)點時璧针,就可以使用層次節(jié)點屬性倆獲取它相關(guān)層次的節(jié)點;- childNodes: 獲取當(dāng)前元素節(jié)點的所有子節(jié)點(非IE下包含了文本和元素類型節(jié)點,也會包含非法嵌套的子節(jié)點渊啰;IE下只包含元素類型節(jié)點)
for(var i=0; i<oBox.childNodes.length; i++){ // 判斷元素節(jié)點 if(box.childNodes[i].nodeType === 1){ // 注意輸出的是大寫的元素名 alert('元素節(jié)點:' + box.childNodes[i].nodeName); } else if(box.childNodes[i].nodeType === 3){ // 判斷文本節(jié)點(有空的文本節(jié)點探橱,來源于換行操作) alert('文本節(jié)點:' + box.childNodes[i].nodeValue); }
}
>
注1: 使用childNodes返回子節(jié)點對象時申屹,可能是元素子節(jié)點,也有可能是文本子節(jié)點隧膏。元素子節(jié)點哗讥,可以通過nodeName或tagName獲取標(biāo)簽名稱,來進(jìn)一步判斷處理胞枕;而文本節(jié)點可以使用nodeValue獲雀松贰;
注2: 在獲取到文本節(jié)點時曲稼,是無法使用innerHTML屬性輸出文本內(nèi)容的(nodeValue和innerHTML第一個區(qū)別即是取值)索绪;
注3: nodeValue和innerHTML第二個區(qū)別就是賦值時,nodeValue會在文本里的HTML轉(zhuǎn)義成特殊字符贫悄,從而達(dá)到形成單純文本的效果瑞驱;
// 結(jié)果: <span>我是span喔</span>
box.childNodes[0].nodeValue = '<span>我是span喔</span>'
// 結(jié)果: 我是span喔
box.innerHTML = '<span>我是span喔</span>'
注4: 在非IE中,標(biāo)準(zhǔn)的DOM具有識別空白文本節(jié)點的功能窄坦;而IE自動忽略了唤反,如果要保持一致的元素節(jié)點,可以直接使用getElmentsByTagName方式鸭津,或者手動刪除/忽略(需要寫封裝操作);
- firstChild: 獲取當(dāng)前元素節(jié)點的第一個子節(jié)點
```
alert(oBox.firstChild.nodeName);
```
- lastChild: 獲取當(dāng)前元素節(jié)點的最后一個子節(jié)點
alert(oBox.lastChild.nodeName);
- parentNode: 獲取當(dāng)前節(jié)點的父節(jié)點
alert( oBox.parentNode.nodeName);
- previousSibling: 獲取當(dāng)前節(jié)點的前一個同級節(jié)點
alert(oBox.lastChild.previousSibling.nodeName);
- nextSibling: 獲取當(dāng)前節(jié)點的后一個同級節(jié)點
alert(oBox.firstChild.nextSibling.nodeName);
- attributes: 獲取當(dāng)前元素節(jié)點的所有屬性節(jié)點集合
oBox.attributes.length // 返回屬性節(jié)點個數(shù)
oBox.attributes[0].nodeType // 節(jié)點類型
oBox.attributes[0].nodeValue // 屬性值
oBox.attributes[0].nodeName // 屬性名
oBox.attributes['title'] // 返回屬性名為title的屬性節(jié)點
- 節(jié)點操作
DOM不單單可以查找節(jié)點彤侍,也可以創(chuàng)建節(jié)點、復(fù)制節(jié)點逆趋、插入節(jié)點盏阶、刪除節(jié)點、替換節(jié)點闻书;
- write(): 可以把任意字符串插入到文檔中
document.write('haha')
- createElement(): 創(chuàng)建一個元素節(jié)點
document.createElement('p'); // 創(chuàng)建一個新元素節(jié)點p
- appendChild(): 將新節(jié)點追加到子節(jié)點列表的末尾
var oUl = document.getElementById("box1"); // 獲取某個元素節(jié)點
var oP = document.createElement('p'); // 創(chuàng)建一個新元素節(jié)點
oUl.appendChild(oP); // 將新元素節(jié)點p名斟,添加到子節(jié)點末尾
- createTextNode(): 創(chuàng)建一個文本節(jié)點
var oText = document.createTextNode(‘哈哈’); // 創(chuàng)建一個文本節(jié)點
- insertBefore(): 將新節(jié)點插入到前面
語法:
// obj父元素,將子元素A插入到子元素B的前面
obj.insertBefore(要插入的元素A, 子元素B);
var oBox = document.getElementById("box"); // 獲取到元素
var oP = document.createElement('p'); // 創(chuàng)建一個p節(jié)點
oBox.parentNode.insertBefore(oP, oBox); // 將p節(jié)點插入到oBox前面
- cloneNode(): 復(fù)制節(jié)點(創(chuàng)建一個節(jié)點的系統(tǒng)開銷相對會較大)
var oBox = document.getElementById("box"); // 獲取到元素
var newBox = oBox.cloneNode(true); // true即表示復(fù)制內(nèi)容
document.body.appendChild(newBox); // 添加到頁面
- removeChild(): 移除節(jié)點
document.body.removeChild(newBox); // 將newBox從body從刪除
> 案例: 簡易日歷