一個完整的JavaScript實現應該由下列三個不同的部分組成:
(1)核心(ECMAScript)
(2)文檔對象模型(DOM)
(3)瀏覽器對象模型(BOM)
(一)DOM(Document Object Model)
1.DOM概念
(1)文本對象模型,是針對XML,HTML的應用程序編程接口。
(2)DOM把整個頁面映射成一個多層節點結構。也就是樹狀結構。
(3)借助DOM提供的接口,可以輕松的刪除,添加,替換和修改任何節點。
(4)在 DOM中 , 每一個元素都是節點。
整個文檔是一個文檔節點。
每個 HTML 標簽是一個元素節點
包含在 HTML 元素中的文本是文本節點
每一個 HTML 屬性是一個屬性節點
注釋屬于注釋節點
JavaScript中的所有節點類型都繼承自Node類型,因此所有節點類型都共享著相同的基本屬性和方法。
每個節點都有一個nodeType屬性,用于表明節點的類型。
常見節點類型:
nodeName和nodeValue屬性
要了解節點的具體信息,可以使用這兩個屬性,不過這兩個屬性的值取決于節點的類型
關系節點
- childNodes
每個節點都有一個childNodes屬性,保存著一個NodeList對象,是一種類數組對象,保存著一組子節點,并且length屬性,特點是可以基于DOM結構動態執行查詢的結果,因此DOM結構的變化能夠自動反映在NodeList對象中
注意:節點的childNodes包含了節點內的所有節點類型(不包括屬性節點),而且標簽內的換行和空格都會被當成一個文本包含在childNodes屬性中
- parentNode
每個節點都有一個parentNode屬性,該屬性指向文檔樹種的父節點,因此,包含在childNodes列表中的所有節點都有相同的父節點,他們的parentNode屬性都指向同一個節點
- previousSibling 和nextSibling屬性
childNodes列表中的每個元素節點相互之間都是同胞節點,可以通過每個節點的previousSibling和nextSibling屬性訪問同一列表的其他節點
- firstChild 和lastChild屬性
在父節點下使用這兩個屬性可以分別獲取childNodes列表下的第一個和最后一個節點.為部分需求操作提供的極大的便利
- hasChildNodes()
這個方法非常簡單實用,在節點包含一或多個子節點的情況下返回true,而無需查詢childNodes的length大小來判斷
- ownerDocument
所有節點都有的最后一個屬性是ownerDocument,該屬性指向整個文檔的文檔節點,不用層層回溯到頂端
舉例:
<!DOCTYPE html>
<html>
<body>
<p id="demo">請點擊按鈕來獲得 <p> 元素的 ownerDocument 的節點類型。</p>
<button onclick="myFunction()">試一下</button>
<script>
function myFunction()
{
var x=document.getElementById("demo");
x.innerHTML=x.ownerDocument.nodeType;//9
}
</script>
</body>
</html>
注意:firstChild,lastChild,nextSibling,previousSibling都會將空格或者換行當做節點處理,(除IE)
所以為了準確地找到相應的元素(其他瀏覽器)
firstElementChild,
lastElementChild,
nextElementSibling,
previousElementSibling
瀏覽器兼容:var test = div1.nextElementSibling || div1.nextSibling;
操作節點
appendChild(新增的節點)
接收一個新增節點作為參數 ,用于向childNodes列表的末尾添加一個節點,并返回新增的節點insertBefore(要插入的節點,作為參照的節點)
插入節點后,被插入的節點會變成參照節點的前一個同胞節點,同時被方法返回,如果參照節點是null,那么insertBefore()和appendChild()是等同的replaceChild(要插入的節點,要替換的節點)
要替換的節點將由這個方法返回并從文檔樹種移除,同時由要插入的節點占據其位置-
removeChild(要刪除的子節點)
這個方法接收一個參數,即要移除的節點,并且被方法返回前面介紹的四個操作方法操作的都是某個節點的子節點,要使用必須先取得父節點
其他方法(所有類型節點都有)
cloneNode(布爾值)
用于創建調用這個方法的節點的一個完全相同的副本,插入布爾值為true則表示深度復制,復制節點和其整個節點樹,否則為淺復制 ,只復制節點本身,復制后返回的節點文本屬于文檔所有,但成為一個"孤兒",需要添加到文檔樹中
注意:cloneNode()方法不會復制添加到DOM節點中的Javascript屬性或者事件處理程序等normalize()
處理文檔樹中的文本節點,如果在節點的后代節點中找到空文本節點,則刪除它,如果找到相鄰的文本節點,則將它們合并為一個文本節點
<!DOCTYPE html>
<html>
<body>
<p id="demo">點擊按鈕添加文本,點擊另一個按鈕來正規化元素。</p>
<button onclick="addTextNode()">添加文本節點</button>
<button onclick="normPara()">對段落進行正規化</button>
<script>
function addTextNode()
{
var y=document.createTextNode("請再次點擊。");
var x=document.getElementById("demo");
x.appendChild(y);
var z=document.getElementById("cc");
z.innerHTML=x.childNodes.length;
}
function normPara()
{
var x=document.getElementById("demo");
x.normalize();
var z=document.getElementById("cc");
z.innerHTML=x.childNodes.length;
}
</script>
<p>上面的段落有 <span id="cc">1</span> 個子節點。</p>
</body>
</html>
HTML的DOM樹節點包括:
元素節點:上圖中<html>、<body>、<p>都是元素節點即標簽
文本節點:向用戶展示的內容,如<li>...</li>中的javascript、Dom、CSS等文本。
屬性節點:元素屬性,如<a>標簽的鏈接屬性
Document對象:
當瀏覽器載入 HTML 文檔, 它就會成為 document 對象。
Document 對象是HTML文檔的根節點與所有其他節點(元素節點,文本節點,屬性節點, 注釋節點)。
Document 對象使我們可以從腳本中對 HTML 頁面中的所有元素進行訪問。
總結:
(1)Document 對象是 Window 對象的屬性,可通過 window.document 屬性對其進行訪問。
(2)Javascript是通過Document類型表示文檔,在瀏覽器中document對象是HTMLDocument的一個實例,表示整個頁面,而且document對象也是window對象的一個屬性,因此可以作為全局對象來訪問
從document節點中取得頁面標簽
- document.documentElement指向HTML頁面中的<html>元素
- document.body指向<body>元素
- document.doctype可以取得對<!DOCTYPE>的引用
- document.title 包含<title>元素中的文本
從document節點中取得頁面的請求信息
- document.URL為地址欄中顯示的URL
- document.domain為頁面的域名
-document.referrer為連接到當前頁面的那個頁面的URL
從document節點中查找元素
- document.getElementById("mydiv")
- document.getElementsByTagName("img"),返回一個HTMLCollection對象,和NodeList對象類似,并且擁有一個方法namedItem()可以傳入元素的name特征來取得集合中的項,可以通過document.getElementsByTagName("*")獲取全部元素
- document.getElementsByClassName("class"):獲取類名相同的元素,Internet Explorer 8 及更早 IE 版本不支持 getElementsByClassName() 方法
- document.getElementsByName():這個方法會返回有給定name特征的所有元素,通常用來獲取單選按鈕.
- document.anchors:包含文檔中所有帶name特性的a元素
- document.forms:包含文檔中所有的form元素
- document.images:包含文檔中所有的img元素
- document.links:包含文檔中所有帶有href特性的a元素
文檔寫入
- document.write(寫入字符串):將輸出流寫入到網頁
- document.writeln(寫入字符串):將輸出流寫入到網頁并換行
注意:必要時候要加轉義字符\ - document.open()和document.close()分別用于打開和關閉網頁的輸出流,如果是在頁面加載期間使用write()或writeln()方法,則不需要用到這兩個方法,調用write或writeln方法時和結束時,瀏覽器會隱式調用這兩個方法
Element類型
判斷元素標簽的最佳實踐:
if(element.tagName.toLowerCase() == "div"){ //在此執行某些操作 }
HTML元素
每個HTML元素都有下列標準特性:
獲取和修改特性
getAttribute(特性名稱attributename)
參數:需要獲得的屬性值的屬性名稱;
不僅可以取得節點的默認特性也可以取得自定義特性(根據HTML5規范,自定義屬性應該加上data-前綴以便驗證),返回對應特性值
注意:傳入style特性后返回的是包含的CSS文本,而通過屬性來訪問style則返回一個對象,因為一系列的問題原因,平時開發只使用對象的屬性來獲取特性,而只有在取得自定義特性值的情況下,才會使用getAttribute()方法setAttribute(特性名稱,特性值)
如果特性存在,則用特性值進行修改,若不存在,則新建特性并賦予特性值,該方法不僅可以操作HTML特性也可以操作自定義特性,而使用對象屬性設置的自定義特性則不會自動成為元素的特性removeAttribute(要刪除的特性名稱)
這個方法用于徹底刪除元素的特性,不僅清除特性的值也會從元素中完全刪除特性
attributes屬性
Element類型是使用attributes屬性的唯一一個DOM節點類型,elment.attributes實質是該元素節點的所有屬性節點的結合,稱為NamedNodeMap,并且擁有它自己的特殊方法:
- getNamedItem(name) 返回nodeName屬性等于name的節點,即返回屬性名對應的屬性節點
- removeNamedItem(name):刪除該屬性節點
- setNamedItem(node) :向列表中添加屬性節點,以nodeName為索引
item(po): 返回位于數字Pos位置處的節點
創建元素
- document.createElement(元素標簽名)
該方法可以傳入完整的元素標簽如
var div = document.createElement("div id="myNewDiv" class = "box"></div>");
注意:這種形式創建的動態元素有很多已知的問題,若要創建一些跟別的元素或者存在相關事件處理的元素,不推薦用這種方法,如iframe標簽 input標簽 有name相同的單選按鈕等
元素的子節點
從上面就可以發現,用元素節點的childNodes遍歷其子元素節點會出現一些換行和空格等形成了文本節點的問題,這意味著在執行某項操作之前,都要檢查一下nodeType屬性,如:
for(var i = 0,len=element.childNodes.length;i<len;i++){
if(element.childNodes[i].nodeType == 1){
//執行某些操作
} }
Text類型
- nodeValue和data屬性:均可以用來訪問Text節點包含的文本
- appendData(text)
- deleteData(offset,count)
- insertData(offset,text)
- replaceData(offset,count,text)使用指定文本來替換此節點以及所有相鄰的文本節點,W3C標準,瀏覽器不支持
- splitText(offset)
- (offset,count)從節點提取數據
length屬性返回文本字符的數目
創建文本節點
document.createTextNode(要插入節點中的文本)
作為參數的文本將按照HTML或XML的格式進行編碼
規范化文本節點
normalize()方法
分割文本節點
與normalize()方法相反的splitText(pos)方法,將一個文本節點分成兩個文本節點
DocumentFragment類型
在所有的節點類型中,只有DocumentFragment在文檔中沒有對應的標記,DOM規范規定文檔片段是一種"輕量級"的文檔,可以包含和控制節點.雖然不能把文檔片段直接添加到文檔中,但可以將它作為一個"倉庫"來使用,即可以在里面保存將來可能添加到文檔中的節點
創建文檔片段
使用document.createDocumentFragment(),返回一個文檔片段對象,繼承了Node的所有方法,可以往里面堆積節點,然后一次性添加到文檔樹中,減低瀏覽器的渲染次數
Attr類型
不常單獨使用,不過多描述
Comment類型 ,CDATASection類型 ,DocumentType類型
不常單獨使用,不過多描述
2.DOM級別
2.1 DOM1級
DOM1級由兩個模塊組成,DOM核心(DOM Core)和DOM HTML。
DOM核心規定的是如何映射基于XML的文檔結構,以便簡化堆文檔中任意部分的訪問和操作。
DOM HTML模塊則在DOM核心的基礎上加以擴展,添加了針對HTML的對象和方法。
2.2 DOM2級
DOM2級在原來的DOM基礎上又擴充了鼠標和用戶界面事件,范圍,遍歷(迭代DOM文檔的方法)等模塊,而且通過對象接口增加了對CSS的支持
DOM視圖(DOM Views):定義了跟蹤不同文檔視圖的接口。
DOM事件:描述事件接口;
DOM樣式:描述處理基于CSS樣式的接口;
DOM遍歷與范圍:描述遍歷和操作文檔樹的接口;
2.3DOM3級
進一步擴展了DOM,引入了以統一方式加載和保存文檔的方法-在DOM加載和保存(DOMLoad and Save)模板中定義
新增了驗證文檔的方法-在DOM驗證(DOM Validation)模板中定義。
DOM3級也對DOM核心進行了擴展,開始支持XML1.0規范,涉及XML Infoset,XPath和XML Base。
注意:DOM0級標準是不存在的,所謂的DOM0級只是DOM歷史坐標中的一個參照點。