深入學(xué)習(xí)DOM模型基礎(chǔ)
本文和大家重點(diǎn)討論一下DOM模型的概念和用法,DOM的全稱是DocumentObjetModule即文檔對(duì)象模型,在Web上把頁面的HTML表現(xiàn)看作一個(gè)有樹型結(jié)構(gòu)的對(duì)象模型,可以通過一些操作接口來對(duì)Document的每一個(gè)子對(duì)象節(jié)點(diǎn)進(jìn)行訪問和操作,這就為Ajax在不刷新頁面的情況下改變頁面顯示數(shù)據(jù)成為了可能。
DOM模型基礎(chǔ)
DOM的全稱是DocumentObjetModule即文檔對(duì)象模型,在Web上把頁面的HTML表現(xiàn)看作一個(gè)有樹型結(jié)構(gòu)的對(duì)象模型,可以通過一些操作接口來對(duì)Document的每一個(gè)子對(duì)象節(jié)點(diǎn)進(jìn)行訪問和操作,這就為Ajax在不刷新頁面的情況下改變頁面顯示數(shù)據(jù)成為了可能。
先來看一個(gè)簡(jiǎn)單的HTML片段:
- <htmlxmlnshtmlxmlns="http://www.w3.org/1999/xhtml">
- <head><title>DOM模型</title></head><body>
- <labeltitlelabeltitle="title1">DOM模型節(jié)點(diǎn)</label></body></html>
在這個(gè)HTML頁面中,只有一個(gè)Label控件,可以根據(jù)節(jié)點(diǎn)的層次畫出這個(gè)頁面的層次結(jié)構(gòu)圖。
通常來說,在HTML文檔中的每一個(gè)標(biāo)簽都表示一個(gè)對(duì)象節(jié)點(diǎn)。而像上面<Lable>這樣的標(biāo)簽是我們的HTML元素節(jié)點(diǎn),而標(biāo)簽中的title=“title1”是一個(gè)屬性節(jié)點(diǎn),而“DOM模型節(jié)點(diǎn)”這樣的文本構(gòu)成了一個(gè)文本節(jié)點(diǎn)。
那么,怎么才能對(duì)DOM模型中的一個(gè)節(jié)點(diǎn)進(jìn)行操作呢,首先要做的是對(duì)這個(gè)節(jié)點(diǎn)進(jìn)行引用。
1.對(duì)文檔節(jié)點(diǎn)的引用
下面列舉一些常用的對(duì)文檔元素節(jié)點(diǎn)的引用方法。
◆document.GetElementById()方法直接引用節(jié)點(diǎn),這個(gè)是我們?cè)趯?shí)際應(yīng)用中最常用的一種方法,在HTML文檔中每一個(gè)元素節(jié)點(diǎn)都可以定義一個(gè)唯一的id屬性,然后使用GetElementById方法就可以準(zhǔn)確地得到對(duì)這個(gè)節(jié)點(diǎn)的引用。
- <htmlxmlnshtmlxmlns="http://www.w3.org/1999/xhtml">
- <head><title>DOM模型</title></head><body><dividdivid="Div1">
- <labeltitlelabeltitle="title1">Dom模型節(jié)點(diǎn)</label></div></body>
- </html><scriptlanguagescriptlanguage="javascript"type="text/javascript">
- <!--var_div1=document.getElementById("Div1");
- alert(_div1.innerHTML);//彈出警告框顯示了標(biāo)簽div中的HTML內(nèi)容
- //<labeltitlelabeltitle="title1">Dom模型節(jié)點(diǎn)</label>--></script>
HTML文檔中每一個(gè)元素節(jié)點(diǎn)都有innerHTML這個(gè)屬性,我們通過對(duì)這個(gè)屬性的訪問可以獲取或者設(shè)置這個(gè)元素節(jié)點(diǎn)標(biāo)簽內(nèi)的HTML內(nèi)容,自IE4.0以來越來越多的瀏覽器支持了這一屬性,通過使用這一屬性使許多繁雜的動(dòng)態(tài)生成HTML的工作變得簡(jiǎn)單。需要注意的是,我們?nèi)绻麑?duì)單標(biāo)記標(biāo)簽,如<img>這一類標(biāo)簽的innerHTML屬性讀取會(huì)得到一個(gè)空字符串,而寫將會(huì)得到一個(gè)錯(cuò)誤。
此外document對(duì)象還有一個(gè)類似的方法GetElementByName,我們可以通過form標(biāo)簽的name屬性對(duì)表單元素節(jié)點(diǎn)進(jìn)行引用,但返回的通常是一個(gè)數(shù)組,因?yàn)楸韱沃械墓?jié)點(diǎn)name屬性的值不是唯一的,可以通過索引器得到每一個(gè)元素的引用。
◆document.getElementByTagName()
可以得到一個(gè)指定標(biāo)記名稱節(jié)點(diǎn)引用的數(shù)組集合,可以通過索引器對(duì)每個(gè)節(jié)點(diǎn)的引用進(jìn)行訪問。
- <htmlxmlnshtmlxmlns="http://www.w3.org/1999/xhtml"><head>
- <title>DOM模型</title></head><body>
- <dividdivid="Div1">節(jié)點(diǎn)1</div><dividdivid="Div2">節(jié)點(diǎn)2</div>
- </body></html><scriptlanguagescriptlanguage="javascript"
- type="text/javascript">
- <!--var_divs=document.getElementsByTagName("div");
- for(vari=0;i<_divs.length;i++)alert(_divs[i].innerHTML);
- //依次顯示了"節(jié)點(diǎn)1"和"節(jié)點(diǎn)2"--></script>
這個(gè)方法通常在要對(duì)整個(gè)文檔的某一類元素節(jié)點(diǎn)進(jìn)行操作時(shí)用到,比如說為全部的圖片添加一個(gè)鼠標(biāo)掠過時(shí)發(fā)生位移的效果,這時(shí)就可以通過這個(gè)方法對(duì)文檔所有的節(jié)點(diǎn)進(jìn)行引用。
◆parentNode和childNodes,可以通過訪問這兩個(gè)屬性獲得當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)和子節(jié)點(diǎn)集合的引用。
- <htmlxmlnshtmlxmlns="http://www.w3.org/1999/xhtml">
- <head><title>DOM模型</title></head>
- <body><dividdivid="Div1"><spanidspanid="sp1">節(jié)點(diǎn)1</span>
- <spanidspanid="sp2">節(jié)點(diǎn)2</span></div></body></html>
- <scriptlanguagescriptlanguage="javascript"type="text/javascript">
- <!--var_nod=document.getElementById("sp1");
- //得到對(duì)sp1的引用var_pNod=_nod.parentNode;
- //得到對(duì)Div1的引用alert(_pNod.innerHTML);
- //顯示父節(jié)點(diǎn)內(nèi)容for(vari=0;i<_pNod.childNodes.length;i++)
- //循環(huán)子節(jié)點(diǎn)alert(_pNod.childNodes[i].innerHTML);
- //依次顯示了每一個(gè)節(jié)點(diǎn)的內(nèi)容--></script>
在這里問題出現(xiàn)了,我們發(fā)現(xiàn)在IE和FF下面對(duì)屬性_pNod.childNodes.length,即子節(jié)點(diǎn)的數(shù)量解釋不同,在IE中為4,而在FF中為5。得到這樣的結(jié)果是因?yàn)閮煞N瀏覽器對(duì)文檔中換行產(chǎn)生的文本節(jié)點(diǎn)的解釋不統(tǒng)一造成的,IE沒有把父節(jié)點(diǎn)與子節(jié)點(diǎn)之間那個(gè)換行作為一個(gè)文本節(jié)點(diǎn),如果要使用這個(gè)屬性就不得不在HTML文檔編寫的時(shí)候避免出現(xiàn)換行,可以將上面的結(jié)構(gòu)改為下面的形式:
- <dividdivid="Div1">
- <spanidspanid="sp1">節(jié)點(diǎn)1</span>
- <spanidspanid="sp2">節(jié)點(diǎn)2</span></div>
雖然這樣寫以后FF和IE都能很好地統(tǒng)一解釋為兩個(gè)子節(jié)點(diǎn),但是損失了文檔的美觀性和易讀性,所以一般都不推薦使用訪問子節(jié)點(diǎn)的方法來引用節(jié)點(diǎn)。
類似的previousSibling和nextSibling也存在類似的問題。這兩個(gè)屬性是用來引用上一個(gè)或者下一個(gè)兄弟節(jié)點(diǎn)的,使用這兩個(gè)屬性時(shí)也存在空白文本節(jié)點(diǎn)的問題,我們也應(yīng)該盡量避免使用這兩個(gè)屬性。#p#
2.文檔元素節(jié)點(diǎn)的操作
得到一個(gè)文檔元素節(jié)點(diǎn)的引用之后,就可以對(duì)這個(gè)節(jié)點(diǎn)進(jìn)行一些控制和操作,以達(dá)到對(duì)HTML顯示進(jìn)行更新的目的。
(1)DOM標(biāo)準(zhǔn)操作,在DOM模型中定義了一套能夠?qū)ξ臋n結(jié)構(gòu)進(jìn)行更新的方法,我們可以通過這些方法創(chuàng)建文檔節(jié)點(diǎn),并將節(jié)點(diǎn)添加到文檔中或者從文檔中刪除。
◆document.createElement(elmName)根據(jù)標(biāo)記名稱創(chuàng)建一個(gè)節(jié)點(diǎn)。
◆document.createTextNode(text)根據(jù)一段文本創(chuàng)建一個(gè)文本節(jié)點(diǎn)。
◆node.appendChild(childNode)將節(jié)點(diǎn)添加到一個(gè)節(jié)點(diǎn)下子節(jié)點(diǎn)的末尾。
◆node.insertBefor(newNode,oldNode)將節(jié)點(diǎn)插入到指定節(jié)點(diǎn)之前,newNode為新節(jié)點(diǎn),oldNode為指定的節(jié)點(diǎn),此節(jié)點(diǎn)必須為node的已經(jīng)存在的一個(gè)子節(jié)點(diǎn)。
◆node.Replace(newNode,oldNode)用新節(jié)點(diǎn)取代一個(gè)舊節(jié)點(diǎn),與上面方法類似,oldNode必須為node的一個(gè)已近存在的子節(jié)點(diǎn)。
◆node.cloneNode(cloneChild)復(fù)制一個(gè)節(jié)點(diǎn),參數(shù)cloneChild是一個(gè)布爾值,表示是否復(fù)制子節(jié)點(diǎn)。
◆node.removeChild(childNode)刪除一個(gè)子節(jié)點(diǎn),需要注意的是該方法將返回被刪除節(jié)點(diǎn)的引用。
下面我們用一個(gè)例子來說明這些方法的使用:
- var_div1=document.getElementById("div1");
- //獲取Div1節(jié)點(diǎn)var_sp3=document.createElement("span");
- //創(chuàng)建一個(gè)<span>元素節(jié)點(diǎn)_sp3.id="span3";
- //將新節(jié)點(diǎn)的屬性id設(shè)為"span3"var_txt1=document.createTextNode("節(jié)點(diǎn)3");
- //創(chuàng)建一個(gè)文本節(jié)點(diǎn)_sp3.appendChild(_txt1);
- //將文本節(jié)點(diǎn)添加到新元素節(jié)點(diǎn)下_div1.appendChild(_sp3);
- //將元素節(jié)點(diǎn)添加到節(jié)點(diǎn)Div1下
- //此時(shí)界面顯示節(jié)點(diǎn)1節(jié)點(diǎn)2節(jié)點(diǎn)3var_sp4=_sp3.cloneNode(true);
- //將元素節(jié)點(diǎn)復(fù)制_sp4.id="span4";
- //為新復(fù)制的節(jié)點(diǎn)設(shè)置id屬性var_txt2=document.createTextNode("節(jié)點(diǎn)4");
- //新建一個(gè)文本節(jié)點(diǎn)_sp4.replaceChild(_txt2,_sp4.childNodes[0]);
- //將節(jié)點(diǎn)_sp4的文本節(jié)點(diǎn)替換_sp3.parentNode.insertBefore(_sp4,_sp3);
- //將節(jié)點(diǎn)_sp4添加到節(jié)點(diǎn)_sp3之前
- //此時(shí)界面顯示節(jié)點(diǎn)1節(jié)點(diǎn)2節(jié)點(diǎn)4節(jié)點(diǎn)3_sp4.parentNode.removeChild(_sp4);
- //刪除節(jié)點(diǎn)_sp4
(2)Table的操作
我們發(fā)現(xiàn)如果通過以上的方法對(duì)表格對(duì)象<table>進(jìn)行操作的話,在IE下將得不到正確的結(jié)果,在IE下必須使用DOM1的方法對(duì)表格進(jìn)行操作。
◆tab.insertRow(idx)在表格指定索引位置添加一行空行,idx為索引位置。
◆tab.deleteRow(idx)在表格指定索引位置刪除一行。
◆row.insertCell(idx)在行的指定索引位置添加一個(gè)空單元格。
◆row.deleteCell(idx)在行的指定位置刪除一個(gè)單元格。
可以通過document.createElement(“table”)創(chuàng)建一個(gè)表格,通過索引器可以訪問talbe的各個(gè)行和單元格,如tab.rows[1].cells[3],這樣我們就能得到表格的第二行第四列的引用,我們可以向操作普通節(jié)點(diǎn)一樣來對(duì)這個(gè)單元格對(duì)象進(jìn)行操作。下面是一個(gè)表格操作的例子,假定這個(gè)表格原來有2行2列。
- vartab=document.getElementById("tab");
- //得到對(duì)表格的引用varrow2=tab.insertRow(2);
- //新增第三行varcell20=row2.insertCell(0);
- //為第三行添加第一個(gè)單元格cell20.innerHTML="20";
- //varcell21=row2.insertCell(1);//為第三行添加第二個(gè)單元格cell21.innerHTML="21";
- tab.rows[1].deleteCell(1);//刪除第二行第二列tab.deleteRow(1);
- //刪除第二行
(3)innerHTML的靈活使用
在IE4.0以后,elm.innerHTML這個(gè)屬性得到大部分瀏覽器的廣泛支持,其易用性使得我們對(duì)文檔的操作得到了很大程度的簡(jiǎn)化,下面來看一個(gè)操作文檔節(jié)點(diǎn)的例子,假設(shè)要對(duì)一個(gè)節(jié)點(diǎn)添加兩個(gè)子節(jié)點(diǎn),并設(shè)置一些屬性,下面是DOM模型標(biāo)準(zhǔn)創(chuàng)建方法:
- var_div1=document.getElementById("div1");
- //得到父節(jié)點(diǎn)var_sp1=document.createElement("span");
- //創(chuàng)建span節(jié)點(diǎn)_sp1.id="span1";
- var_txt1=document.createTextNode("節(jié)點(diǎn)1");
- //創(chuàng)建文本節(jié)點(diǎn)_sp1.appendChild(_txt1);
- //將文本加入到span節(jié)點(diǎn)下_div1.appendChild(_sp1);
- //將span節(jié)點(diǎn)加入到父節(jié)點(diǎn)下
這樣寫我們通過六行代碼完成了功能的實(shí)現(xiàn),下面來看使用innerHTML的情況
- var_div2=document.getElementById("div2");
- _div2.innerHTML="<spanid='span1'>節(jié)點(diǎn)2</span>";
運(yùn)行后發(fā)現(xiàn),只使用了兩行代碼而得到了完全相同的效果,并且這種方法還更為直觀一些,可讀性還更強(qiáng)??梢娛褂胕nnerHTML屬性,可以更為方便高效地改變文檔結(jié)構(gòu),這使得在大多數(shù)情況下都使用innerHTML來操作文檔,但是標(biāo)準(zhǔn)的DOM模型方法在特定的環(huán)境下也有不可取代的作用,在編碼時(shí)要靈活判斷,選擇合適的方法解決問題。
【編輯推薦】
- JavaScript DOM特性與應(yīng)用詳解
- HTML DOM入門級(jí)知識(shí)手冊(cè)
- HTML DOM display屬性語法實(shí)例解析
- 深入了解JavaScript HTML DOM對(duì)象
- 術(shù)語匯編 Javascript DOM技術(shù)探究