JavaScript在Web開發中的主要作用是與用戶交互,在網頁上添加某種行爲。JavaScript允許在網頁加載到瀏覽器中後,完全改變網頁的所有方面,JavaScript在網頁上提供這個功能的基礎是文檔對象模型(Document Object Model,DOM),這是網頁的樹狀表示方法。DOM爲開發人員提供了一種表示網頁中的所有元素的方式,以便在JavaScript中通過一組通用的屬性和方法來訪問。通過JavaScript修改相應的DOM屬性,就能修改頁面中的圖形,表格,表單,樣式,甚至文本自身。
DOM模型與BOM模型是兩個不同的概念。目前可以將BOM視爲一個代表瀏覽器各種特性的依賴瀏覽器的對象,包括瀏覽器的按鈕,URL地址欄,標題欄,瀏覽器窗口空間以及網頁的各部分。而DOM僅處理瀏覽器窗口或網頁(即HTML文檔)中的內容,任何瀏覽器都可以使用完全相同的代碼來訪問和操作文檔的內容。
DOM與瀏覽器和平臺無關,開發人員可以使用JavaScript代碼動態更新頁面,這些代碼在任何兼容DOM的瀏覽器上都能正常運行,無須做任何修改。DOM將頁面的內容表示爲通用的樹結構,實現了這種無關性。在BOM中訪問某個對象時,需要查找與該瀏覽器部分相關的屬性。而DOM只需要在頁面的樹型結構中導航到與瀏覽器無關的節點或屬性上。
文檔對象模型
文檔對象模型(DOM)是一種獨立於瀏覽器類型來表示文檔的方法。它允許開發人員通過一組通用的對象,屬性,方法和事件來訪問文檔,並通過腳本動態修改網頁內容。W3C以DOM標準的形式提供了一組可用於所有瀏覽器的通用對象,屬性和方法。
文檔對象模型(DOM)和瀏覽器對象模型(BOM)之間存在兩個主要的區別。
1.DOM僅包含Web頁面的文檔,而BOM提供了瀏覽器各個領域的腳步編程訪問,包括按鈕,標題欄以及頁面的某些部分。
2.BOM專用於某個瀏覽器。
Html是標準化的,因此網頁只能包含HTML語言支持的特性,如表單,表格和圖片等,且需要一種通用的方法,來訪問這些特性。此時需要使用DOM,它提供了HTML文檔的統一表達方式,即將整個HTML文檔/網頁表示爲樹型結構。實際上,可以將任何HTML表示爲樹型結構。通過DOM訪問元素的能力,取決於將頁面表示爲層次結構的能力。
樹型結構是表示層次結構的一種圖標方式,以層次方式導航DOM比使用完全線性的方法有意義。DOM中的樹型結構如下所示:
樹的頂層是文檔和包含頁面中所有其他元素的元素,文檔就是根節點。節點只是樹中的一個點,表示某個元素,元素的屬性或特性,或者元素包含的文本。根節點包含了所有的其他節點,如DTD聲明以及根元素(包含所有其他元素的HTML或XML元素)。在HTML文檔中,根元素應總是<html>元素。在根元素之下,是根元素包含的HTML元素。HTML頁面一般在<html>元素中包含<head>和<body>元素。這些元素表示爲根元素節點下的節點,而根元素節點本身在樹頂部的根節點之下。
DOM核心對象
DOM提供了一組具體的對象,屬性和方法,通過JavaScript可以訪問它們,以便瀏覽DOM的樹型結構。
對象 | 說明 |
---|---|
Node | 文檔中的每個節點都有自己的Node對象 |
NodeList | 這是Node對象的列表 |
NamedNodeMap | 允許按名稱(而不是按索引)訪問所有Node對象 |
有了基本的DOM對象,就可以在網頁文檔中添加,替換或移除網頁的各個部分,而不會影響整個頁面的結構,因爲只是改變了樹型結構中的節點。實際上,有不同的對象表示樹中不同類型的節點。
DOM中的所有東西都是節點,所以節點肯定有各種類型。Node對象有不同的子對象,來表示每種類型的節點。DOM中三種主要的節點類型,即元素,屬性和文本。
對象 | 說明 |
---|---|
Document | 文檔的根節點 |
DocumentType | XML文檔的DTD或模式類型 |
DocumentFragment | 文檔部分的臨時存儲空間 |
EntityReference | XML文檔中的實體引用 |
Element | 文檔中的一個元素 |
Attr | 文檔中元素的一個屬性 |
ProcessingInstruction | 處理指令 |
Comment | XML文檔或HTML文檔中的註釋 |
Text | 構成元素子節點的純文本 |
CDATASection | XML文檔中的CDATA部分 |
Entity | DTD中未解析的實體 |
Notation | DTD中聲明的記號 |
這些對象都繼承了Node對象的所有屬性和方法,還包含了自己的一些屬性和方法。
這些介紹三個主要的對象Node,Element和Document,通過這三個對象,就可以創建,修改和導航樹型結構。
Document對象及其方法
Document對象提供的方法允許查找單個元素或元素組,創建新元素,屬性和文本節點。只有Document對象的方法可以在頁面上查找,創建和刪除元素。
document對象的方法 | 說明 |
---|---|
getElementById(idValue) | 根據所提供的元素的id值,返回對該元素的引用(節點) |
getElementByTagName(tagName) | 根據參數中提供的標記,返回對一組元素的引用(節點列表) |
querySelector(cssSelector) | 返回與給定CSS選擇器匹配的第一個元素的引用(節點) |
querySelectorAll(cssSelector) | 返回與給定CSS選擇器匹配的一組元素的引用(節點列表) |
第一個方法getElementById()要求確保在頁面中快速訪問的每個元素都使用id屬性,否則該方法返回null(表示缺失或未知的值)。可以使用該方法,返回一個對頁面上帶id屬性的任意HTML元素的引用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 id="heading1">My Heading</h1>
<p id="paragraph1">This is some text in a paragraph</p>
<script>
alert(document.getElementById("heading1").innerText);
var h1Element=document.getElementById("heading1");
h1Element.style.color="red";
</script>
</body>
</html>
第二個方法getElementsByTagName參數是放在引號中的元素名,例如可以是表單元格”td”,超鏈接元素”a”等等。該方法只返回一個對象,但是該對象是一個元素集合。集合類似於數組,可以通過索引號來訪問集合中的特定元素,可以使用方括號來指定,也可以使用NodeList獨享的item()方法。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table border="1">
<tr>
<td>Row 1 Cell 1</td>
</tr>
<tr>
<td>Row 1 Cell 2</td>
</tr>
</table>
<script>
var tdElement=document.getElementsByTagName("td").item(0);
tdElement.style.color="green";
</script>
</body>
</html>
上述代碼將第一個表單元格的字體顏色設置爲綠色。
第三個方法querySelector()用於獲取匹配所提供CSS選擇器的第一個元素,它可以方便地獲取沒有id屬性的元素。
例如下面的HTML:
<p class="sub-title">This is a <span>special</span> paragraph element that contains <span> some text </span> </p>.
使用querySelector()方法可以使用如下代碼獲取這個HTML中的第一個<span/>元素。
var firstSpan=document.querySelector(".sub-title span");
所提供的CSS選擇器匹配包含在父元素中,CSS類爲sub-title的所有<span/>元素。
document對象的方法 | 說明 |
---|---|
createElement(elementName) | 使用指定的標記名創建一個元素節點,返回所創建的元素 |
createTextNode(text) | 創建並返回包含所提供文本的文本節點 |
下面的代碼創建了一個文本節點和一個h1元素。
var nextText=document.createTextNode("New Text");
var newElem=document.createElement("h1");
樹型結構包含頁面上所有的元素和節點,並將它們放在一個層次結構中。如果要引用這個結構,需要使用document對象的一個特殊屬性,該屬性返回文檔的最外層元素。在HTML中,它總是<html/>元素。返回這個元素的屬性是documentElement。documentElement屬性以對象的形式返回對這個元素的引用,確切地是Element對象。
var container=document.documentElement;
alert(container.tagName);
上面的代碼會在一個信息框中顯示Html。
Element對象
Element對象常用屬性和方法:
Element屬性 | 說明 |
---|---|
tagName | 獲取元素的標記名稱 |
getAttribute(attributeName) | 返回所提供的屬性的值;如果該屬性不存在,就返回null或空字符串 |
setAttribute(attributeName,value) | 用指定的值設置屬性 |
removeAttribute(attributeName) | 從元素中刪除指定的屬性及其值 ,代之以默認值 |
例如下面的代碼設置文本的位置:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 id="heading1">My Heading</h1>
<p id="paragraph1">This is some text in a paragraph</p>
<script>
var h1Element=document.getElementById("heading1");
h1Element.setAttribute("align","center");
alert(h1Element.getAttribute("align"));
h1Element.removeAttribute("align");
</script>
</body>
</html>
Node對象
從網頁中獲取了元素後,如果要遍歷元素,屬性和文本,需要沿着樹型結構的節點移動。至於節點包含什麼內容,甚至節點是什麼類型,都無關緊要。因此需要使用DOM核心規範的一個對象Node,整個樹型結構都是由這些基本的Node對象構成。
如下表列出了Node對象的常用屬性,這些屬性提供了節點的信息,即當前節點是元素,屬性還是文本,並可以從一個節點移動到另一個節點。
Node對象的屬性 | 說明 |
---|---|
firstChild | 返回元素的第一個子節點 |
lastChild | 返回元素的最後一個子節點 |
previousSibling | 在同級子節點中,返回當前子節點的前一個兄弟節點 |
nextSibling | 在同級子節點中,返回當前子節點的後一個兄弟節點 |
ownerDocument | 返回包含節點的文檔的根節點 |
parentNode | 返回屬性結構中包含當前節點的元素 |
nodeName | 返回節點的名稱 |
nodeType | 返回一個數字,表示節點的類型 |
nodeValue | 以純文本格式獲取或設置節點的值 |
例如下面的代碼顯示heading1節點的下一個兄弟節點
var h1Element=document.getElementById("heading1");
h1Element.style.color="red";
alert(h1Element.nextElementSibling.nodeType);
Node對象的屬性可以導航DOM,而其方法提供了完全不同的功能:在DOM中添加和刪除節點,從根本上改變了HTML文檔的結構。
Node對象的方法 | 說明 |
---|---|
appendChild(newNode) | 將一個新node對象添加到子節點列表的末尾;該方法返回追加的節點 |
cloneNode(cloneChildren) | 返回當前節點的一個副本;該方法的參數是一個布爾值,如果該值爲true,則克隆當前節點及其所有的子節點;如果該值爲false,則僅克隆當前節點,而不包含其子節點 |
hasChildNodes() | 如果節點有子節點,則返回true,否則返回false |
insertBefore(newNode,referenceNode) | 在referenceNode指定的節點前,插入一個node對象,返回新插入的節點 |
removeChilde(childNode) | 從node對象的子節點列表中,刪除一個子節點,並返回刪除的節點 |
例如下面的代碼使用DOM方法創建HTML元素和文本,並添加到文檔末尾:
var nextText=document.createTextNode("New Text");
var newElem=document.createElement("h1");
newElem.appendChild(nextText);
document.body.appendChild(newElem);
操作DOM
DHTML是瀏覽器加載HTML頁面後,操縱該頁面的技術。
改變頁面元素的外觀,主要指的是改變HTML元素的CSS屬性。在JavaScript中,有兩種方式:
1.使用style屬性改變各個CSS屬性
要修改特定的CSS屬性,必須使用style屬性。所有瀏覽器都實現了這個對象,該對象直接映射到元素的style屬性。style對象包含CSS屬性,使用該對象,可以修改瀏覽器支持的任何CSS屬性。
CSS屬性名通常匹配CSS樣式表使用的名稱,例如改變元素文本顏色,可使用color屬性:
var divAdvert=document.getElementById("divAdvert");
divAdvert.style.color="blue";
對於包含連字符(-)的CSS屬性,需要去掉連字符,並把連字符後的第一個字母改成大寫,例如:
divAdvert.style.backgroundColor="gray";
可以使用style對象來獲取聲明的樣式,如果要獲取的style屬性沒有用style屬性(即內聯樣式)或style對象設置,則不能獲取屬性的值。例如下面的代碼包含一個樣式表和</div>元素:
<style>
#divAdvert{
background-color:gray;
}
</style>
<div id="divAdvert" style="color: green">Test</div>
<script>
var divAdvert=document.getElementById("divAdvert");
alert(divAdvert.style.backgroundColor);//提示 空 字符串
alert(divAdvert.style.color);//提示 green
</script>
當瀏覽器顯示這個元素時,會顯示灰底綠字。但是獲取backgroundColor時得到空字符串,獲取color時得到green值,是由於style對象直接映射到元素的style屬性上。如果在<style/>塊中設置樣式聲明,或在外部樣式表中聲明,則不能通過style對象來獲取該屬性的值。
2.修改元素的class屬性值
使用元素的class屬性可以把CSS類賦予元素。在DOM中,該屬性通過className屬性來使用,可以通過JavaScript修改className屬性,爲元素應用另一個樣式規則。
element.className=sNewClassName;
使用className屬性來修改元素樣式具有兩個優點,一是減少了需要編寫的JavaScript代碼量,二是可將樣式信息從JavaScript文件中提取出來,放在它所屬的CSS文件中。
例如下面的代碼給divAdvert元素採用了新的樣式規則,瀏覽器就會改變其顯示方式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#divAdvert{
font:20pt arial;
}
.new-style{
font-style: italic;
text-decoration: underline;
}
</style>
</head>
<body>
<div id="divAdvert">
Here is an advertisement.
</div>
<script>
var divAdvert=document.getElementById("divAdvert");
divAdvert.className="new-style";
</script>
</body>
</html>
DOM腳本編程不僅能改變元素在頁面上的顯示方式,還可以通過JavaScript改變元素的位置。
在JavaScript中移動內容,可以使用position屬性來改變所需位置的類型,使用left和top屬性可以定位元素。
例如下面的代碼把position屬性設置爲絕對位置,把元素移動到距離左邊界和上邊界各100像素的地方。
divAdvert.style.position="absolute";
divAdvert.style.left="100px";
divAdvert.style.top="100px";
注意:必須在設置位置值時指定單位,否則,瀏覽器將無法定位該元素。