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