DOM(Document Object Model)——文件物件模型
什麼是DOM?
Document Object Model (DOM)是HTML和XML文件的程式設計介面。它提供了上述文件的一種結構化表示,同時也定義了一種通過程式來改變文件結構,風格,以及內容的方式。DOM用一組結構化的節點以及物件來表示文件。本質上就是將網頁和指令碼語言以及程式語言連線起來。
一個網頁是一個文件。這個文件可以被顯示在瀏覽器視窗中,也可以以html原始碼的形式顯示。這兩中情況中,文件都是同一個。DOM提供了另一種方式來表示,儲存,操作這個文件。DOM是網頁的一種完全的物件導向的表示方法,可以通過指令碼語言(比如說JavaScript)來改變。
W3C DOM標準形成了當今大多數瀏覽器的DOM基礎。許多瀏覽器提供超出W3C標準的擴充套件,所以當用在可能被擁有不同DOM的各種瀏覽器使用的場合時 一定要多加註意
DOM標準主要要為:微軟DOM與W3C DOM,一般IE實現的是微軟DOM,而其它瀏覽器則不同程度的實際了W3C DOM
DOM發展史
- DOM Level Zero ,事實上從來不存在DOM 0版本,只是人們的戲稱。只是在W3C DOM出現之前,不同瀏覽器(主要是IE與NN)實現的DOM相互排斥,1996年的瀏覽器大戰所產生的DHTML就是所謂的DOM 0,它是指令碼程式設計師的惡夢
- DOM Level 1 包括DOM Core和DOM HTML。前者提供了基於XML的文件結構圖。後者新增了一些HTML專用的物件和方法,從而擴充套件了DOM Core.目前IE在內的大部分桌面瀏覽器都通過不同方式實現了DOM 1
- DOM Level 2 引入幾個新模組:DOM檢視,事件,樣式,遍歷和範圍。IE只實現了一部分,火狐瀏覽器幾乎全部實現,除IE之外的瀏覽器也實現了大部分
- DOM Level 3 引入了以統一的方式載入和儲存文件的方法。DOM Core被擴充套件支援所有的XML1.0的特性。火狐瀏覽器之類實現了少部分
在開始階段,JavaScript和DOM是緊密的聯絡在一起的,但是最終他們將發展為獨立的實體。網頁的內容儲存在DOM中並且可以被JavaScript訪問和處理,所以我們可以得到寫下這個近似的等式:
API(網頁或者XML頁面)=DOM + JS(指令碼語言)
DOM被設計為獨立於任何特定的程式語言,通過協調一致的API以確保這種文件的結構化表現形式是有效的。雖然DOM的實現可以建立在任何語言上,但是在這裡我們專注於JavaScript上的DOM實現!
儘管DOM很大程度上受到瀏覽器中動態HTML發展的影響,但W3C還是將它最先應用於XML。
DOM與BOM的關係
DOM與BOM的關係?——BOM包含DOM
DOM與BOM結構檢視
DOM Core
文件物件模型-DOM,就是使用樹檢視來形容HTML程式碼,看下面的一張HTML頁面的原始碼
<html> <head> <title>樹!樹!到處都是樹!</title> </head> <body> <h1>樹!樹!到處都是樹!</h1> <p>HTML那層層巢狀的程式碼就像一棵<em>樹</em>一樣!</p> <div>一層一層的樹<img src="../images/stach_heap.gif" /> </div> </body> </html>
瀏覽器接受該頁面並將之轉換為樹形結構
獲取元素常用方法
document物件是BOM的一部分,同時也是HTML DOM的HTMLDocument物件的一種表現形式,反過來說,它也是XML DOM Document物件。JavaScript中的大部分處理DOM的過程都利用document物件,所以我們訪問文件需要使用BOM提供的這個入口。
var d = document; alert(d);//這僅僅表明document這個物件是存在的
document物件有三個強大的方法,可以獲取頁面的任何元素
var p1 = document.getElementById("p1");//獲取ID為p1的那個元素 //在一個文件中ID必須是唯一的,getElementById方法只會返回一個元素 alert(p1.tagName); var allP = document.getElementsByTagName("p");//獲取文件中所有p標籤 //因為頁面中標籤相同的元素很多,所以即使頁面中只有一個p元素,getElementsByTagName也會返回一個集合 for (var i=0;i < allP.length;i++) { alert(allP[i].innerHTML);//像陣列一樣訪問其中的每個元素 } //getElementsByTagName還可以使用萬用字元*來獲取所有的元素 var allTags = document.getElementsByTagName("*"); alert(allTags.length); //更強大的是,getElementsByTagName不但可以在document物件上呼叫,也可以在其它HTML元素上呼叫 var p2 = document.getElementById("p2"); var p2ps = p2.getElementsByTagName("em");//將獲取p2下面的em元素,而不獲取p2之外的em //還有一個通過name來獲取元素的方法:getElementsByName var radios = document.getElementsByName("check");//獲取所有name為check的元素
由於name可以重複,getElementsByName方法始終返回一個集合,不管頁面中name是否是唯一的。 IE 6.0和Opera 7.5在這個方法的使用上還存在一些錯誤。首先,它們還會返回id等於給定名稱的元素。第二,它們僅僅檢查<input/>和<img/>元素。
獲取和設定元素屬性——getAttribute與setAttribute方法
var p1 = document.getElementById("p1"); alert(p1.getAttribute("id")); p1.setAttribute("title","Value");
節點基礎
文件根節點
var de = document.documentElement; alert(de.tagName);
由於IE 5.5中的DOM實現的錯誤,document.documentElement會返回<body/>元素。IE 6.0已經修復了這個錯誤。
獲取head與body
//本來可以使用getElementsByTagName的 var head = document.getElementsByTagName("head")[0]; var body = document.getElementsByTagName("body")[0];
還可以使用節點,在使用節點前,先了解一些節點基礎知識
常用節點型別
- 元素節點——文件中具有標籤的節點
- 文字節點——標籤中不是註釋的文字塊
常用的節點屬性
- nodeType——節點型別,元素節點是1,文字節點是3
- nodeValue——節點值,元素節點為空,文字節點的nodeValue屬性即為文字內容
- firstChild——該元素節點包含的第一個子節點
- lastChild——該元素節點包含的最後一個子節點
- nextSibling——該節點的後一個兄弟節點
- previousSibling——該節點的前一個兄弟節點
- childNodes——子節點列表,可以通過node.childNodes[index](或node.childNodes.item(index))來獲取子節點
- nodeName——節點名稱,對於元素節點,返回tagName,對於文字,則返回#text
考慮下面的HTML程式碼所表示的節點結構
<p> Some Text </p>
上面的HTML程式碼將會解析成兩個節點:元素節點——p標籤,文字節點——Some Text.也就是說,標籤中包含的一些文字也是節點,那麼空格之類的非列印字元會不會被當作文字節點呢?
不同瀏覽器在判斷何為Text節點上存在一些差異。某些瀏覽器,如Mozilla,認為元素之間的空白(包括換行符)都是Text節點;而另一些瀏覽器,如IE,會全部忽略這些空白!!
var de = document.documentElement; var head = de.firstChild;//html下面第一個元素,可能是head var body = de.lastChild;//html下面最後一個元素,可能是body
答案並不確定,但是仍然有辦法解決——使用節點型別檢測,每個節點都有nodeType屬性,指明它的節點型別。對於元素節點,它的值是1,而對於文字節點,它的值是3
var de = document.documentElement; var head = de.firstChild.nodeType==1?de.firstChild:de.firstChild.nextSibling; var body = de.lastChild.nodeType==1?de.lastChild:de.lastChild.previousSibling;] //還可以使用childNodes var de = document.documentElement; var head = de.childNodes[0].nodeType==1?de.childNodes[0]:de.childNodes[0].nextSibling; var head = de.childNodes[1].nodeType==1?de.childNodes[1]:de.childNodes[1].previousSibling;
HTML DOM
HTML DOM用物件來表示HTML標籤,考慮下面的程式碼——
<img src="../images/stack_heap.jpg" alt="記憶體堆疊" onclick="alert('Hello!')" /> //對於上面的img標籤,瀏覽器解析時會將其轉換成下面的物件 { src:"../images/stack_heap.jpg", alt:"記憶體堆疊", onclick:"alert('Hello!')", tagName:"IMG" }; //其實不止這些屬性
一般所說的DOM是指XML DOM,而W3C也為HTML頁面提供了更快捷的DOM——HTML DOM!使用HTML DOM,能使訪問HTML標籤的屬性就像訪問JavaScript建立的物件的屬性一樣簡單.
var imgObj = document.getElementById("imgObj"); alert(imgObj.src);//獲取src屬性如此簡單
使用HTML DOM也使得訪問頁面一些元素變得更加簡單
var bodyTag = document.documentElement.lastChild;//DOM標準方式 bodyTag = document.body;//HTML DOM方式 var titleTag = document.getElementsByTagName("title")[0].firstChild.nodeValue;//DOM標準方式 titleTag = document.title;//HTML DOM方式 //HTML DOM不僅僅可以用來獲取內容,也可以設定 document.title ="Change The Title!!!";