html dom與javascript的關系 -我們用JavaScript對網頁(HTML)進行的所有操作都是通過DOM進行的
一,什麽是DOM (參考源http://www.cnblogs.com/chaogex/p/3959723.html)
DOM是什麽
DOM全稱為The Document Object Model,應該理解為是一個規範,定義了HTML和XML文檔的邏輯結構和文檔操作的編程接口。
文檔邏輯結構
DOM實際上是以面向對象方式描述的對象模型,它將文檔建模為一個個對象,以樹狀的結構組織(本文稱之為“文檔樹”,樹中的對象稱為“節點”)。
每個文檔包含1個document節點,0個或1個doctype節點以及0個或多個元素節點等。document節點是文檔樹的根節點。
如對於HTML文檔,DOM 是這樣規定的:
- 整個文檔是一個文檔節點
- 每個 HTML 標簽是一個元素節點
- 包含在 HTML 元素中的文本是文本節點
- 每一個 HTML 屬性是一個屬性節點
- 註釋屬於註釋節點
節點與文檔內容是一一對應的關系,節點之間有層次關系。
例如下面的hmlt文檔:
<!DOCTYPE html> <html> <head> <title>文檔標題</title> </head> <body> <a href="">我的鏈接</a> <h1>我的標題</h1> </body> </html>
會被建模為下面的文檔樹:
又如下面的html文檔:
<!DOCTYPE html> <html class=e> <head>
<title>Aliens?</title>
</head> <body>Why yes.</body> </html>
會被建模為下面的文檔樹:
文檔操作
程序員可以使用DOM定義的接口來獲得對文檔中所有元素進行訪問的入口,創建文檔,瀏覽文檔結構,添加、修改或刪除文檔元素和內容。
HTML或XML文檔中的所有的內容都可以通過使用DOM定義的接口來操作。
DOM到底是對象模型還是編程接口?
總的來說,DOM應該理解為是1個規範。
站在實現(如瀏覽器)和使用者(如程序員)的角度來看,DOM就是一套文檔節點的編程接口,只要實現了接口,就可以使用接口成員來操作文檔;站在設計和制定的角度來看,DOM是一個對象模型,它將文檔內容建模為對象並組織為樹狀結構,定義了這些對象的行為和屬性以及這些對象之間的關系。
DOM不是什麽
- DOM不是一個數據結構集,並沒有定義數據結構。
- DOM沒有定義文檔中什麽信息是相關的或者文檔中的信息是如何組織的。
如對於XML,這些是在XML Information Set中指定的。DOM只是這些信息集的API。(Application Programming Interface,應用程序編程接口)
DOM的分級
上面討論的DOM是1級DOM,具體就是 DOM CORE和DOM HTML,它將HTML和XML文檔映射為對由層次對象(節點)組成的樹。
根據W3C DOM規範,DOM有1級、2級、3級以及最新的4級.
二,什麽是HTML DOM (參考源 http://blog.csdn.net/liu_shi_jun/article/details/40817297)
HTML DOM 是:
- HTML 的標準對象模型
- HTML 的標準編程接口
- W3C 標準
HTML DOM 定義了所有 HTML 元素的對象和屬性,以及訪問它們的方法。
換言之,HTML DOM 是關於如何獲取、修改、添加或刪除 HTML 元素的標準。
下面說的dom實際上指的是html dom。
腳本開發人員可以通過文檔對象的屬性、方法和事件來掌控、操縱和創建動態的網頁元素。每一個網頁元素(一個HTML標簽)都對應著一個對象(object,所謂“對象”,用白話說就是“東西”。object這個詞在臺灣通常翻譯成“物件”)。網頁上的標簽是一層層嵌套的,最外面的一層是<HTML>,文檔對象模型也這樣一層層嵌套著,但是通常被理解成一棵樹的形狀。樹根是window或document對象,相當於最外層的標簽的外圍,也就是整個文檔。樹根之下(這棵樹的圖通常是倒著畫,就好像遺傳譜系或者家譜那樣。樹根就是唯一的共同祖先)是子一級的對象,子對象也有它自己的子對象,除了根對象以外,所有的對象都有自己的父對象,同一對象的子對象之間就是兄弟的關系。
在這種由“父子兄弟”組成的“單性繁殖家族圖譜樹”框架結構中,每個網頁元素都可以被確切地定位。文檔對象模型把整張網頁組織成這樣的一個樹狀的結構,樹結構中的每一個元素都被視為一個節點(node)。包括JavaScript在內的各種編程語言都可以通過文檔對象模型來訪問和改變網頁的各種細節。
萬維網協會(World Wide Web Consortium,W3C)已經給文檔對象模型制定了一系列標準,並且正在制定更多的相關標準。當代的瀏覽器除支持其中的一部分標準之外,還支持某些早在W3C標準制定以前就流行了的歷史既成的編程接口。也就是說現在瀏覽器使用的技術歷史由來紛繁復雜,有些人們普遍使用的DOM技術並無標準可依。
我們將深入所有通用DOM的細節(包括IE瀏覽器中“與眾不同”的某些技術),以全面掌握面向實踐的技術。
我們用JavaScript對網頁(HTML)進行的所有操作都是通過DOM進行的。DOM屬於瀏覽器,而不是JavaScript語言規範裏的規定的核心內容,所以如果你下載一個JavaScript語言的參考幫助文檔來查的話,就連婦孺皆知的document.write方法也找不到。
簡而言之,DOM可以理解為一個訪問或操作HTML各種標簽的實現標準。(參考源:http://www.cnblogs.com/iOS-mt/p/5600959.html)
對於一個HTML來說,文檔節點Document(看不到的)是它的根節點,對應的對象便是document對象(嚴格講是子類HTMLDocument對象,下面單獨介紹Document類型時會指出)。
換句話說存在一個文檔節點Document,然後它有子節點,比如通過document.getElementsByTagName("html"),得到類型為元素節點的Element html。
每一段HTML標記都可以用相應的節點表示,例如:
HTML元素通過元素節點表示,註釋通過註釋節點表示,文檔類型通過文檔類型節點表示等。
一共定義了12種節點類型,而這些類型又都繼承自Node類型。
所以我們首先講Node類型,因為這個類型的方法是所有節點都會繼承的。
二、Node類型(基類,所有節點都繼承了它的方法)
Node是所有節點的基類型,所有節點都繼承自它,所以所有節點都有一些共同的方法和屬性。
先講Node類型的屬性
首先是nodeType屬性,用來表明節點類型的,例如:
document.nodeType; // 返回 9 ,其中document對象為文檔節點Document的實例
這裏面,9代表的就是DOCUMENT_NODE節點的意思,可以通過Node.DOCUMENT_NODE查看節點對應的數字
document.nodeType === Node.DOCUMENT_NODE; // true
至於一共有哪些節點,每個節點對應的數字又是多少,這個可以問谷歌就知道了。反正常用的就是元素節點Element(對應數字為1)和文本節點Text(對應數字為3)
然後常用的還有nodeName和nodeValue
對於元素節點 nodeName就是標簽名,nodeValue就是null
對於文本節點 nodeName為"#text"(chrome裏面測試的),nodeValue就是實際的值
每個節點還有childNodes屬性,這是個十分重要的屬性,它保存了這個節點所有直接子元素
調用childNodes返回的是一個NodeList對象,它極其像數組,但是有一個最關鍵的地方,它是動態查詢的,也就是說每次調用它都會對DOM結構查詢,所以對它的使用需要慎重,註意性能。
訪問childNodes可以使用數組下標或者item方法。
然後各個節點還存在各種屬性讓它們可以相互訪問,下圖很好的總結了
比較有用的方法和屬性:
1、hasChildNodes()
如果包含子節點就返回true,比查詢childNodes的length來的簡單。
2、ownerDocument
返回文檔節點的引用(在html裏面也就是document對象)
再介紹下Node類型常用的方法
appendChild()方法可以在節點的childNodes的末尾增加一個節點,值得註意的是如果這個節點是已經存在在文檔中的,那麽便會刪除原節點,感覺上就像是移動節點一樣。
insertBefore()方法接受兩個參數,一個是插入的節點,另外一個是參照的節點。如果第二個參數為null,則insertBefore和appendChild效果一樣。否則便會把節點插入到參照節點之前。這裏要註意的是,如果第二個參數不為null,那麽插入的節點不能是已經存在的節點。
replaceChild()方法可以替換節點,接受兩個參數,需要插入的節點和需要替換的節點。返回被替換掉的節點。
removeChild()移除節點。這裏有個常見需求,比如我有一個節點 #waste-node ,那麽如何移除它呢?
var wasteNode = document.getElementById("waste-node"); wasteNode.parentNode.removeClhid(wasteNode); // 先拿到父節點,再調用removeClild刪除自己
這裏先暫停一下,不知道大家註意到沒有,以上的幾個方法都是操作某個節點的子節點,也就是說,操作前必須找到父節點(通過parentNode來找)
接下來說下復制節點的方法:
cloneNode();復制節點,接受一個參數 true或者false。如果true就是復制那個節點和它的子節點。如果是false,就是復制節點本身(復制出來的節點就會沒有任何子元素)。這個方法返回復制的節點,如果需要操作它,那麽需要借助前面講的4個方法來把這個節點放入到html中去。
至此,Node類型的常見屬性和方法都介紹完了。結合開頭講的,所有節點類型都繼承自Node類型,所以這些方法是所有節點都有的。
三、Document類型
最開始講DOM是什麽的時候提到了Document類型。其實關於這個類型最重要的是它的一個子類HTMLDocument有一個實例對象document。而這個document對象是我們最常用的一個對象了。
document對象又掛載在window對象上,所以在瀏覽器就可以直接訪問document了。
老規矩,先講講document對象的屬性,等會講講它的方法。
document對象上的一些屬性
document.childNodes 繼承自上面講的Node類型,可以返回文檔的直接子節點(通常包括文檔聲明和html節點)
document.documentElement 可以直接拿到html節點的引用(等價於document.getElementsByTagName("html")[0])。
document.body body節點的引用
document.title 頁面的title,可以修改,會改變瀏覽器標簽上的名字
document.URL 頁面的url
document.referrer 取得referrer,也就是打開這個頁面的那個頁面的地址,做來源統計時候比較有用
document.domain 取得域名,可以設置,但是通常只能設置為不包含子域名的情況,在一些子域名跨域情況下有效。
接下來介紹兩個熟悉的方法
getElementById 和 getElementsByTagName
getElementById,傳入id,得到元素節點。裏面的參數區分大小寫(IE8-不區分)。註意:如果有多個id相同的元素,則返回第一個。IE7-裏面表單元素的name也會被當做id來使用。
getElementsByTagName 根據標簽取得元素,得到的是HTMLCollection類型。如果傳入的是 "*" ,則可以取得全部元素。
還有一個是只有HTMLDocument類型(也就是document對象)才有的方法 getElementsByName 顧名思義,根據name返回元素。
document對象還有一些集合,例如document.forms 可以返回所有的form表單。類型也是HTMLCollection。
說到HTMLCollection,就再說說它
HTMLCollection就是一個包含一個或多個元素的集合,和上面講的NodeList還挺像的。HTMLCollection這個類型有兩個方法,一個是通過下標(或者.item())得到具體元素,還有就是通過[‘name‘](或者.namedItem())獲得具體元素。
最後,關於document對象還有一套重要的方法,那便是
write() writeln() open() close()
open和close分別是打開和關閉網頁的輸出流,在頁面加載過程中,就相當於open狀態。這兩個方法一般不會去用它。
然後重要的方法就是write和writeln,它們都是向頁面寫入東西,區別就是後者會多加入一個換行符。
註意的是:在頁面加載的過程中,可以使用這兩個方法向頁面添加內容。如果頁面已經加載完了,再調用write,會重寫整個頁面。
還有一點,如果要動態寫入腳本 例如 <script>xxx</script>這樣的 ,那麽要註意把</script>分開來拼裝下,否則會被誤以為是腳本結束的標誌,導致這個結束符匹配到上面一個開始符。可以這樣寫"<scr" + "ipt>";
四、Element類型
接下來講講最重要也是最常見的一個類型,Element類型。
我們日常所操作的都是Element類型(實質是HTMLElement,這裏為了方便理解,就簡單這麽說),比如
document.getElementById("test")
返回的就是Element類型。我們日常所說的“DOM對象”,通常也就是指Element類型的對象。
然後說說這個類型的常見屬性:
首先最開始說的Node類型上的那些屬性方法它都有,這個就不再重復了,主要說說它自己獨有的。
首先是tagName,這個和繼承自Node類型的nodeName一樣。都是返回標簽名,通常是大寫,結果取決於瀏覽器。所以在做比較
的時候最好是調用下類似toLowerCase()這種方法再做比較。
說說上面提到過的HTMLElement類型
HTMLElement類型繼承自Element類型,也是HTML元素的實際類型,我們在瀏覽器裏用的元素都是這個類型。
這個類型都具有一些標準屬性,比如:
id 元素的唯一標識
title 通常是鼠標移上去時候會顯示的信息
className 類名
等等,這幾個屬性是可讀寫的,也就是說你改變他們會得到相應的效果。
除了屬性外,還有幾個重要的方法
首先說說操作節點屬性的方法
getAttribute 、setAttribute 、removeAttribute這3個方法。
這些是操作屬性最常用的方法了,怎麽用就不說了,很簡單,顧名思義。
還有一個attributes屬性,保存了元素的全部屬性。
這裏停下來,出個問題,ele.className 和 ele.getAttribute("class")返回的結果是不是同一個東西?
解答這個問題,我要說一個重要知識點,一個元素的屬性結構是這麽來的,比如一個inpnt元素
<input id="test" checked="checked">
那麽這個元素的屬性被包含在 input.attributes裏面,比如你在html元素上看到的class、id或者你自己定義的data-test這種屬性。
然後 getAttribute 、setAttribute 、removeAttribute這3個方法可以認為是快捷的取attributes集合的方法。而直接input.id或者input.className都是直接掛在input下的屬性,和attributes是同級的。所以返回的東西也許看過去一樣,實際是不一樣的,不信你可以試試input.checked這input.getAttribute("checked")試試。
關於這個知識點,詳細的說可以再寫一篇文章,在我的博客 從is(":checked")說起 中有談到過,大家可以看看這篇文章和文章後的討論,便可以知道是怎麽一回事。
總得來說,這3個方法通常用了處理自定義的屬性,而不是id、class等這種“公認特性”。
接下來說說創建元素
document.createElement()可以創建一個元素,比如:
document.createElement("div");
一般之後可以為元素設置屬性,兩種方法,一種是直接node.property還可以node.setAttribute("propertyName","value")。等
但是做完這些之後,這個元素還是沒有在頁面中,所以你還得通過最上面講的類似appendChild這些方法把元素添加到頁面裏面。
在IE中,還可以直接穿整個HTML字符串進去,來創建元素,比如
document.createElement("<div>test</div>");
最後,元素節點也支持HTMLDocument類型的那些查找方法,比如getElementsByTagName。不過它只會找自己後代的節點。所以可以這麽寫代碼
document.getElementById("test").getElementsByTagName("div"); // 找到id為test元素下的所有div節點
五、Text類型
這個類型很特殊,也是第三常見類型(第一第二分別就是Document和Element)。
這個節點簡單來說就是一段字符串。
有個很重要的特征就是,它沒有子元素(不過這個仔細想想也知道= =)
訪問text節點的文本內容,可以通過nodeValue或者data屬性。
下面簡單說說它提供的一些方法
appendData(); // 在text末尾加內容 deleteData(offset, count); // 從offset指定的位置開始刪除count個字符
還有insertDate、replaceData、splitText等方法,就不一一說了,用的機會很少,可以用的時候再查閱。
然後它還有一個lenght屬性,返回字符長度的。
這裏說一個常見的坑。比如下面這個html結構
<ul> <li></li> <li></li> </ul>
這裏,ul的第一個子節點(firstChild)是什麽呢?第一眼看過去,肯定認為是li了,但是實際上,你會發現不是li,而是一個文本節點!
這是因為瀏覽器認為ul和第一個li之間有空白字符,所以就有文本節點了。
這裏一個常見的問題就是遍歷ul的childNodes的時候,遍歷的元素一定要判斷下nodeType是不是等於1(等於1就代表是元素節點),這樣才能跳過這個坑。否則你也可以刪除所有的空格和換行符。
創建文本節點的方法是document.createTextNode
然後接下來和操作Element類型一樣,就是再插入到元素中,瀏覽器就可以看到了。
六、其他的一些類型 Comment、DocumentType和DocumentFragment
這些不常用的一句話帶過把
Comment是註釋節點
DocumentType就是doctype節點,通過docment.doctype來訪問
DocumentFragment這個節點是一個文檔片段,偶爾會用到。
比如一種常見的用法是,在一個ul中插入3個li。
如果你循環插入3次,那麽瀏覽器就要渲染3次,對性能有蠻大的影響。
所以大家一般這麽做
先
var fragment = document.createDocumentFragment();
然後循環把li,用appendChild插入到fragment裏面
最後在一次把fragment插入到ul裏面。這樣就會很快。
html dom與javascript的關系 -我們用JavaScript對網頁(HTML)進行的所有操作都是通過DOM進行的