|
級別: 中級
Brett McLaughlin (brett@newInstance.com), 作家兼編輯, O‘Reilly Media Inc.
2006 年 10 月 12 日
本系列的上一篇文章中考察了文檔對象模型(DOM)編程中涉及到的概念——Web 瀏覽器如何把網(wǎng)頁(yè)看作一棵樹(shù),現在您應該理解了 DOM 中使用的編程結構。本期教程將把這些知識用于實(shí)踐,建立一個(gè)簡(jiǎn)單的包含一些特殊效果的 Web 頁(yè)面,所有這些都使用 JavaScript 操縱 DOM 來(lái)創(chuàng )建,不需要重新加載或者刷新頁(yè)面。
前面兩期文章已經(jīng)詳細介紹了文檔對象模型或者 DOM,讀者應該很清楚 DOM 是如何工作的了。(前兩期 DOM 文章以及 Ajax 系列更早文章的鏈接請參閱參考資料。)本教程中將把這些知識用于實(shí)踐。我們將開(kāi)發(fā)一個(gè)簡(jiǎn)單的 Web 應用程序,其用戶(hù)界面可根據用戶(hù)動(dòng)作改變,當然要使用 DOM 來(lái)處理界面的改變。閱讀完本文之后,就已經(jīng)把學(xué)習到的關(guān)于 DOM 的技術(shù)和概念付諸應用了。
假設讀者已經(jīng)閱讀過(guò)上兩期文章,如果還沒(méi)有的話(huà),請先看一看,切實(shí)掌握什么是 DOM 以及 Web 瀏覽器如何將提供給它的 HTML 和 CSS 轉化成單個(gè)表示網(wǎng)頁(yè)的樹(shù)狀結構。到目前為止我一直在討論的所有 DOM 原理都將在本教程中用于創(chuàng )建一個(gè)能工作的(雖然有點(diǎn)簡(jiǎn)單)基于 DOM 的動(dòng)態(tài) Web 頁(yè)面。如果遇到不懂的地方,可以隨時(shí)停下來(lái)復習一下前面的兩期文章然后再回來(lái)。
從一個(gè)示例應用程序開(kāi)始
|
關(guān)于代碼的說(shuō)明
為了把注意力集中到 DOM 和 JavaScript 代碼上,我編寫(xiě) HTML 的時(shí)候有些隨意地采用內聯(lián)樣式(比如 h1 和 p 元素的 align 屬性)。雖然對實(shí)驗來(lái)說(shuō)這樣做是可接受的,但是對于開(kāi)發(fā)的任何產(chǎn)品應用程序,我建議花點(diǎn)時(shí)間把所有的樣式都放到外部 CSS 樣式表中。
|
|
我們首先建立一個(gè)非常簡(jiǎn)單的應用程序,然后再添加一點(diǎn) DOM 魔法。要記住,DOM 可以移動(dòng)網(wǎng)頁(yè)中的任何東西而不需要提交表單,因此足以和 Ajax 媲美;我們創(chuàng )建一個(gè)簡(jiǎn)單的網(wǎng)頁(yè),上面只顯示一個(gè)普通的舊式大禮帽,還有一個(gè)標記為 Hocus Pocus! 的按鈕(猜猜這是干什么的?)
初始 HTML
清單 1 顯示了這個(gè)網(wǎng)頁(yè)的 HTML。除了標題和表單外,只有一個(gè)簡(jiǎn)單的圖片和可以點(diǎn)擊的按鈕。
清單 1. 示例應用程序的 HTML
<html>
<head>
<title>Magic Hat</title>
</head>
<body>
<h1 align="center">Welcome to the DOM Magic Shop!</h1>
<form name="magic-hat">
<p align="center">
<img src="topHat.gif" />
<br /><br />
<input type="button" value="Hocus Pocus!" />
</p>
</form>
</body>
</html>
|
可以在本文后面的下載中找到這段 HTML 和本文中用到的圖片。不過(guò)我強烈建議您只下載那個(gè)圖片,然后隨著(zhù)本文中逐漸建立這個(gè)應用程序自己動(dòng)手輸入代碼。這樣要比讀讀本文然后直接打開(kāi)完成的應用程序能夠更好地理解 DOM 代碼。
查看示例網(wǎng)頁(yè)
這里沒(méi)有什么特別的竅門(mén),打開(kāi)網(wǎng)頁(yè)可以看到圖 1 所示的結果。
圖 1. 難看的大禮帽
關(guān)于 HTML 的補充說(shuō)明
應該 注意的重要一點(diǎn)是,清單 1 和圖 1 中按鈕的類(lèi)型是 button 而不是提交按鈕。如果使用提交按鈕,單擊該按鈕將導致瀏覽器提交表單,當然表單沒(méi)有 action 屬性(完全是有意如此),從而會(huì )造成沒(méi)有任何動(dòng)作的無(wú)限循環(huán)。(應該自己試試,看看會(huì )發(fā)生什么。)通過(guò)使用一般輸入按鈕而不是提交按鈕,可以把 javaScript 函數和它連接起來(lái)與瀏覽器交互而無(wú)需 提交表單。
向示例應用程序添加元素
現在用一些 JavaScript、DOM 操作和小小的圖片戲法裝扮一下網(wǎng)頁(yè)。
使用 getElementById() 函數
顯然,魔法帽子沒(méi)有兔子就沒(méi)有看頭了。這里首先用兔子的圖片替換頁(yè)面中原有的圖片(再看看圖 1),如圖 2 所示。
圖 2. 同樣的禮帽,這一次有了兔子
完成這個(gè) DOM 小戲法的第一步是找到網(wǎng)頁(yè)中表示 img 元素的 DOM 節點(diǎn)。一般來(lái)說(shuō),最簡(jiǎn)單的辦法是用 getElementById() 方法,它屬于代表 Web 頁(yè)面的 document 對象。前面已經(jīng)見(jiàn)到過(guò)這個(gè)方法,用法如下:
var elementNode = document.getElementById("id-of-element");
|
為 HTML 添加 id 屬性
這是非常簡(jiǎn)單的 JavaScript,但是需要修改一下 HTML:為需要訪(fǎng)問(wèn)的元素增加 id 屬性。也就是希望(用帶兔子的新圖片)替換的 img 元素,因此將 HTML 改為清單 2 的形式。
清單 2. 增加 id 屬性
<html>
<head>
<title>Magic Hat</title>
</head>
<body>
<h1 align="center">Welcome to the DOM Magic Shop!</h1>
<form name="magic-hat">
<p align="center">
<img src="topHat.gif" id="topHat" />
<br /><br />
<input type="button" value="Hocus Pocus!" />
</p>
</form>
</body>
</html>
|
如果重新加載(或者打開(kāi))該頁(yè)面,可以看到毫無(wú)變化,增加 id 屬性對網(wǎng)頁(yè)的外觀(guān)沒(méi)有影響。不過(guò),該屬性可以幫助 JavaScript 和 DOM 更方便地處理元素。
抓住 img 元素
現在可以很容易地使用 getElementById() 了。已經(jīng)有了需要元素的 ID,即 topHat,可以將其保存在一個(gè)新的 JavaScript 變量中。在 HTML 頁(yè)面中增加清單 3 所示的代碼。
清單 3. 訪(fǎng)問(wèn) img 元素
<html>
<head>
<title>Magic Hat</title>
<script language="JavaScript">
function showRabbit() {
var hatImage = document.getElementById("topHat");
}
</script>
</head>
<body>
<h1 align="center">Welcome to the DOM Magic Shop!</h1>
<form name="magic-hat">
<p align="center">
<img src="topHat.gif" id="topHat" />
<br /><br />
<input type="button" value="Hocus Pocus!" />
</p>
</form>
</body>
</html>
|
現在打開(kāi)或重新加載該網(wǎng)頁(yè)同樣沒(méi)有什么驚奇的地方。雖然現在能夠訪(fǎng)問(wèn)圖片,但是對它還什么也沒(méi)有做。
修改圖片,麻煩的辦法
完成所需修改有兩種方法:一種簡(jiǎn)單,一種麻煩。和所有的好程序員一樣,我也喜歡簡(jiǎn)單的辦法;但是運用較麻煩的辦法是一次很好的 DOM 練習,值得您花點(diǎn)時(shí)間。首先看看換圖片比較麻煩的辦法;后面再重新分析一下看看有沒(méi)有更簡(jiǎn)單的辦法。
用帶兔子的新照片替換原有圖片的辦法如下:
- 創(chuàng )建新的
img 元素。
- 訪(fǎng)問(wèn)當前
img 元素的父元素,也就是它的容器。
- 在已有
img 元素之前 插入新的 img 元素作為該容器的子級。
- 刪除原來(lái)的
img 元素。
- 結合起來(lái)以便在用戶(hù)單擊 Hocus Pocus! 按鈕時(shí)調用剛剛創(chuàng )建的 JavaScript 函數。
創(chuàng )建新的 img 元素
通過(guò)上兩期文章應該記住 DOM 中最關(guān)鍵的是 document 對象。它代表整個(gè)網(wǎng)頁(yè),提供了 getElementById() 這樣功能強大的方法,還能夠創(chuàng )建新的節點(diǎn)?,F在要用到的就是這最后一種性質(zhì)。
具體而言,需要創(chuàng )建一個(gè)新的 img 元素。要記住,在 DOM 中一切都是節點(diǎn),但是節點(diǎn)被進(jìn)一步劃分為三種基本類(lèi)型:
還有其他類(lèi)型,但是這三種可以滿(mǎn)足 99% 的編程需要。這里需要一個(gè) img 類(lèi)型的新元素。因此需要下列 JavaScript 代碼:
var newImage = document.createElement("img");
|
這行代碼可以創(chuàng )建一個(gè) element 類(lèi)型的新節點(diǎn),元素名為 img。在 HTML 中基本上就是:
要記住,DOM 會(huì )創(chuàng )建結構良好的 HTML,就是說(shuō)這個(gè)目前為空的元素包括起始和結束標簽。剩下的就是向該元素增加內容或屬性,然后將其插入到網(wǎng)頁(yè)中。
對內容來(lái)說(shuō),img 是一個(gè)空元素。但是需要增加一個(gè)屬性 src,它指定了要加載的圖片。您也許認為要使用 addAttribute() 之類(lèi)的方法,但情況并非如此。DOM 規范的制定者認為程序員可能喜歡簡(jiǎn)潔(的確如此?。?,因此他們規定了一個(gè)方法同時(shí)用于增加新屬性和改變已有的屬性值:setAttribute()。
如果對已有的屬性調用 setAttribute(),則把原來(lái)的值替換為指定的值。但是,如果調用 setAttribute() 并指定一個(gè)不 存在的屬性,DOM 就會(huì )使用提供的值增加一個(gè)屬性。一個(gè)方法,兩種用途!因此需要增加下列 JavaScript 代碼:
var newImage = document.createElement("img");
newImage.setAttribute("src", "rabbit-hat.gif");
|
它創(chuàng )建一個(gè)圖片元素然后設置適當的資源屬性?,F在,HTML 應該如清單 4 所示。
清單 4. 使用 DOM 創(chuàng )建新圖片
<html>
<head>
<title>Magic Hat</title>
<script language="JavaScript">
function showRabbit() {
var hatImage = document.getElementById("topHat");
var newImage = document.createElement("img");
newImage.setAttribute("src", "rabbit-hat.gif");
}
</script>
</head>
<body>
<h1 align="center">Welcome to the DOM Magic Shop!</h1>
<form name="magic-hat">
<p align="center">
<img src="topHat.gif" id="topHat" />
<br /><br />
<input type="button" value="Hocus Pocus!" />
</p>
</form>
</body>
</html>
|
可以加載該頁(yè)面,但是不要期望有任何改變,因為目前所做的修改實(shí)際上還沒(méi)有影響頁(yè)面。另外,如果再看看任務(wù)列表中的第 5 步,就會(huì )發(fā)現還沒(méi)有調用我們的 JavaScript 函數!
獲得原始圖片的父元素
現在有了要插入的圖片,還需要找到插入的地方。但是不能將其插入到已有的圖片中,而是要將其插入到已有圖片之前然后再刪除原來(lái)的圖片。為此需要知道已有圖片的父元素,實(shí)際上這就是插入和刪除操作的真正關(guān)鍵所在。
應該記得,前面的文章中曾經(jīng)指出 DOM 確實(shí)把網(wǎng)頁(yè)看成一棵樹(shù),即節點(diǎn)的層次結構。每個(gè)節點(diǎn)都有父節點(diǎn)(樹(shù)中更高層次的節點(diǎn),該節點(diǎn)是它的一個(gè)子級),可能還有自己的子節點(diǎn)。對于圖片來(lái)說(shuō),它沒(méi)有子級 —— 要記住圖片是空元素,但是它肯定有父節點(diǎn)。甚至不需要知道父節點(diǎn)是什么,但是需要訪(fǎng)問(wèn)它。
為此,只要使用每個(gè) DOM 節點(diǎn)都有的 parentNode 屬性即可,比如:
var imgParent = hatImage.parentNode;
|
確實(shí)非常簡(jiǎn)單!可以肯定這個(gè)節點(diǎn)有子節點(diǎn),因為已經(jīng)有了一個(gè):原來(lái)的圖片。此外,完全不需要知道它是一個(gè) div、p 或者頁(yè)面的 body,都沒(méi)有關(guān)系!
插入新圖片
現在得到了原來(lái)圖片的父節點(diǎn),可以插入新的圖片了。很簡(jiǎn)單,有多種方法可以添加子節點(diǎn):
insertBefore(newNode, oldNode)
appendChild(newNode)
因為希望把新圖片放在舊圖片的位置上,需要使用 insertBefore()(后面還要使用 removeChild() 方法)??墒褂孟旅孢@行 JavaScript 代碼把新圖片元素插入到原有圖片之前:
var imgParent = hatImage.parentNode;
imgParent.insertBefore(newImage, hatImage);
|
現在原圖片的父元素有了兩個(gè) 子元素:新圖片和緊跟在后面的舊圖片。必須指出,這里包圍 這些圖片的內容沒(méi)有變,而且這些內容的順序也和插入之前完全相同。僅僅是這個(gè)父節點(diǎn)中增加了一個(gè)子節點(diǎn),即舊圖片之前的新圖片。
刪除舊圖片
現在只需要刪除舊圖片,因為網(wǎng)頁(yè)中只需要新圖片。很簡(jiǎn)單,因為已經(jīng)得到了舊圖片元素的父節點(diǎn)。只要調用 removeChild() 并把需要刪除的節點(diǎn)傳遞給它即可:
var imgParent = hatImage.parentNode;
imgParent.insertBefore(newImage, hatImage);
imgParent.removeChild(hatImage);
|
現在,用新圖片替換舊圖片的工作已基本完成了。HTML 應該如清單 5 所示。
清單 5. 用新圖片替換舊圖片
<html>
<head>
<title>Magic Hat</title>
<script language="JavaScript">
function showRabbit() {
var hatImage = document.getElementById("topHat");
var newImage = document.createElement("img");
newImage.setAttribute("src", "rabbit-hat.gif");
var imgParent = hatImage.parentNode;
imgParent.insertBefore(newImage, hatImage);
imgParent.removeChild(hatImage);
}
</script>
</head>
<body>
<h1 align="center">Welcome to the DOM Magic Shop!</h1>
<form name="magic-hat">
<p align="center">
<img src="topHat.gif" id="topHat" />
<br /><br />
<input type="button" value="Hocus Pocus!" />
</p>
</form>
</body>
</html>
|
連接 JavaScript
最后一步,可能也是最簡(jiǎn)單的,就是把 HTML 表單連接到剛剛編寫(xiě)的 JavaScript 函數。需要每當用戶(hù)點(diǎn)擊 Hocus Pocus! 按鈕的時(shí)候運行 showRabbit() 函數。為此只要向 HTML 中增加一個(gè)簡(jiǎn)單的 onClick 事件處理程序即可。
<input type="button" value="Hocus Pocus!" onClick="showRabbit();" />
|
這種簡(jiǎn)單的 JavaScript 編程應該非常容易了。將其添加到 HTML 頁(yè)面中,保存它然后在 Web 瀏覽器中打開(kāi)。頁(yè)面初看起來(lái)應該和圖 1 相同,但是點(diǎn)擊 Hocus Pocus! 后應該看到圖 3 所示的結果。
圖 3. 兔子戲法
替換圖片,簡(jiǎn)單的辦法
如果回顧替換圖片的步驟,再看看節點(diǎn)的各種方法,可能會(huì )注意到方法 replaceNode()。該方法可用于把一個(gè)節點(diǎn)替換為另一個(gè)節點(diǎn)。再考慮一下前面的步驟:
- 創(chuàng )建新的
img 元素。
- 訪(fǎng)問(wèn)當前
img 元素的父元素,也就是它的容器。
- 在已有
img 元素之前 插入新的 img 元素作為該容器的子元素。
- 刪除原來(lái)的
img 元素。
- 連接起來(lái)以便在用戶(hù)點(diǎn)擊 Hocus Pocus! 的時(shí)候調用剛剛創(chuàng )建的 JavaScript 函數。
使用 replaceNode() 可以減少需要的步驟數??梢詫⒌?3 步和第 4 步合并在一起:
- 創(chuàng )建新的
img 元素。
- 訪(fǎng)問(wèn)當前
img 元素的父元素,也就是它的容器。
- 用創(chuàng )建的新元素替換舊的
img 元素。
- 連接起來(lái)以便在用戶(hù)點(diǎn)擊 Hocus Pocus! 的時(shí)候調用剛剛創(chuàng )建的 JavaScript 函數。
這看起來(lái)不是什么大事,但確實(shí)能夠簡(jiǎn)化代碼。清單 6 說(shuō)明了這種修改:去掉了 insertBefore() 和 removeChild() 方法調用。
清單 6. 用新圖片替換舊圖片(一步完成)
<html>
<head>
<title>Magic Hat</title>
<script language="JavaScript">
function showRabbit() {
var hatImage = document.getElementById("topHat");
var newImage = document.createElement("img");
newImage.setAttribute("src", "rabbit-hat.gif");
var imgParent = hatImage.parentNode;
imgParent.replaceChild(newImage, hatImage);
}
</script>
</head>
<body>
<h1 align="center">Welcome to the DOM Magic Shop!</h1>
<form name="magic-hat">
<p align="center">
<img src="topHat.gif" id="topHat" />
<br /><br />
<input type="button" value="Hocus Pocus!" onClick="showRabbit();" />
</p>
</form>
</body>
</html>
|
當然這不是什么大的修改,但是說(shuō)明了 DOM 編碼中一件很重要的事:執行一項任務(wù)通常有多種方法。如果仔細審閱可用 DOM 方法看看是否有更簡(jiǎn)單的方法可以完成任務(wù),很多時(shí)候都會(huì )發(fā)現可以將四五個(gè)步驟壓縮為兩三個(gè)步驟。
替換圖片,(真正)簡(jiǎn)單的辦法
既然指出了執行一項任務(wù)幾乎總是有更簡(jiǎn)單的方法,現在就說(shuō)明用兔子圖片替換帽子圖片的簡(jiǎn)單得多 的辦法。閱讀本文的過(guò)程中有沒(méi)有想到這種方法?提示一下:與屬性有關(guān)。
要記住,圖片元素很大程度上是由其 src 屬性控制的,他引用了某個(gè)地方的文件(不論是本地 URI 還是外部 URL)。到目前為止,我們一直用新圖片替換圖片節點(diǎn),但是直接修改已有圖片的 src 屬性要簡(jiǎn)單得多!這樣就避免了創(chuàng )建新節點(diǎn)、尋找父節點(diǎn)和替換舊節點(diǎn)的所有工作,只要一步就能完成了:
hatImage.setAttribute("src", "rabbit-hat.gif");
|
這樣就夠了!看看清單 7,它顯示了這種解決方案,包括整個(gè)網(wǎng)頁(yè)。
清單 7. 修改 src 屬性
<html>
<head>
<title>Magic Hat</title>
<script language="JavaScript">
function showRabbit() {
var hatImage = document.getElementById("topHat");
hatImage.setAttribute("src", "rabbit-hat.gif");
}
</script>
</head>
<body>
<h1 align="center">Welcome to the DOM Magic Shop!</h1>
<form name="magic-hat">
<p align="center">
<img src="topHat.gif" id="topHat" />
<br /><br />
<input type="button" value="Hocus Pocus!" onClick="showRabbit();" />
</p>
</form>
</body>
</html>
|
這是 DOM 最棒的一點(diǎn):更新屬性的時(shí)候網(wǎng)頁(yè)馬上就會(huì )改變。只要圖片指向新的文件,瀏覽器就加載該文件,頁(yè)面就更新了。不需要重新加載,甚至不需要創(chuàng )建新的圖片元素!結果仍然和圖 3 相同,只不過(guò)代碼簡(jiǎn)單得多了。
把兔子藏起來(lái)
現在網(wǎng)頁(yè)看起來(lái)很漂亮,但是仍然有點(diǎn)原始。雖然兔子從帽子中跳出來(lái)了,但是屏幕下方的按鈕仍然顯示 Hocus Pocus! 和調用 showRabbit()。這就是說(shuō)如果在兔子出來(lái)之后仍然點(diǎn)擊按鈕,就是在浪費處理時(shí)間。更重要的是,它毫無(wú)用處,而沒(méi)有用的按鈕不是好東西。我們來(lái)看看能否利用 DOM 再作一些修改,無(wú)論兔子在帽子里還是出來(lái)都讓這個(gè)按鈕派上用場(chǎng)。
修改按鈕的標簽
最簡(jiǎn)單的是當用戶(hù)點(diǎn)擊按鈕之后改變它的標簽。這樣就不會(huì )看起來(lái)像還有什么魔法,網(wǎng)頁(yè)中最糟糕的就是暗示用戶(hù)錯誤的東西。在修改按鈕的標簽之前需要訪(fǎng)問(wèn)該節點(diǎn),而在此之前需要引用按鈕 ID。這是老套路了,清單 8 為按鈕增加了 id 屬性。
清單 8. 增加 id 屬性
<html>
<head>
<title>Magic Hat</title>
<script language="JavaScript">
function showRabbit() {
var hatImage = document.getElementById("topHat");
hatImage.setAttribute("src", "rabbit-hat.gif");
}
</script>
</head>
<body>
<h1 align="center">Welcome to the DOM Magic Shop!</h1>
<form name="magic-hat">
<p align="center">
<img src="topHat.gif" id="topHat" />
<br /><br />
<input type="button" value="Hocus Pocus!" id="hocusPocus"
onClick="showRabbit();" />
</p>
</form>
</body>
</html>
|
現在用 JavaScript 訪(fǎng)問(wèn)按鈕很簡(jiǎn)單了:
function showRabbit() {
var hatImage = document.getElementById("topHat");
hatImage.setAttribute("src", "rabbit-hat.gif");
var button = document.getElementById("hocusPocus");
}
|
當然,您可能已經(jīng)輸入了下面這行 JavaScript 來(lái)改變按鈕的標簽值。這里再次用到了 setAttribute():
function showRabbit() {
var hatImage = document.getElementById("topHat");
hatImage.setAttribute("src", "rabbit-hat.gif");
var button = document.getElementById("hocusPocus");
button.setAttribute("value", "Get back in that hat!");
}
|
通過(guò)這個(gè)簡(jiǎn)單的 DOM 操作,兔子跳出來(lái)之后按鈕的標簽馬上就會(huì )改變?,F在,HTML 和完成的 showRabbit() 函數如清單 9 所示。
清單 9. 完成的網(wǎng)頁(yè)
<html>
<head>
<title>Magic Hat</title>
<script language="JavaScript">
function showRabbit() {
var hatImage = document.getElementById("topHat");
hatImage.setAttribute("src", "rabbit-hat.gif");
button.setAttribute("value", "Get back in that hat!");
}
</script>
</head>
<body>
<h1 align="center">Welcome to the DOM Magic Shop!</h1>
<form name="magic-hat">
<p align="center">
<img src="topHat.gif" id="topHat" />
<br /><br />
<input type="button" value="Hocus Pocus!" id="hocusPocus"
onClick="showRabbit();" />
</p>
</form>
</body>
</html>
|
把兔子收回去
從此新的按鈕標簽中可能已經(jīng)猜到,現在要把兔子收回帽子中去?;旧虾头磐米映鰜?lái)完全相反:將圖片的 src 屬性再改回舊圖片。創(chuàng )建一個(gè)新的 JavaScript 函數來(lái)完成這項任務(wù):
function hideRabbit() {
var hatImage = document.getElementById("topHat");
hatImage.setAttribute("src", "topHat.gif");
var button = document.getElementById("hocusPocus");
button.setAttribute("value", "Hocus Pocus!");
}
|
實(shí)際上僅僅把 showRabbit() 函數的功能翻轉了過(guò)來(lái)。將圖片改為原來(lái)的沒(méi)有兔子的大禮帽,抓取按鈕,將標簽改為 Hocus Pocus!
事件處理程序
現在這個(gè)示例應用程序有一個(gè)大問(wèn)題:雖然按鈕的標簽 改變了,但是單擊按鈕時(shí)的動(dòng)作沒(méi)有 變。幸運的是,當用戶(hù)單擊按鈕時(shí)可以使用 DOM 改變事件或者發(fā)生的動(dòng)作。因此,如果按鈕上顯示 Get back in that hat!,點(diǎn)擊的時(shí)候需要運行 hideRabbit()。相反,一旦兔子藏了起來(lái),按鈕又返回來(lái)運行 showRabbit()。
|
避免使用 addEventHandler()
除了 onclick 屬性外,還有一個(gè)方法可用于添加 onClick 或 onBlur 這樣的事件處理程序,毫不奇怪這個(gè)方法就叫 addEventHandler()。不幸的是,Microsoft? Internet Explorer? 不支持這個(gè)方法,如果在 JavaScript 中使用它,就會(huì )有數百萬(wàn) Internet Explorer 用戶(hù)除了錯誤外從網(wǎng)頁(yè)中什么也看不到(可能還有抱怨)。不使用這個(gè)方法,應用本文中介紹的辦法也能達到同樣的效果,而且在 Internet Explorer 上也有效。
|
|
查看 HTML 就會(huì )發(fā)現這里處理的事件是 onClick。在 JavaScript 中,可以通過(guò)按鈕的 onclick 的屬性來(lái)引用該事件。(要注意,在 HTML 中該屬性通常稱(chēng)為 onClick,其中 C 大寫(xiě);而在 JavaScript 中則稱(chēng)為 onclick,全部小寫(xiě)。)因此可以改變按鈕觸發(fā)的事件:只要賦給 onclick 屬性一個(gè)新的函數。
但是有點(diǎn)細微的地方:onclick 屬性需要提供函數引用——不是函數的字符串名稱(chēng),而是函數本身的引用。在 JavaScript 中,可以按名稱(chēng)引用函數,不需要帶括號。因此可以這樣修改點(diǎn)擊按鈕時(shí)執行的函數:
button.onclick = myFunction;
|
因此在 HTML 中作這種修改很簡(jiǎn)單??纯?a target="_blank" >清單 10,它切換按鈕觸發(fā)的函數。
清單 10. 改變按鈕的 onClick 函數
<html>
<head>
<title>Magic Hat</title>
<script language="JavaScript">
function showRabbit() {
var hatImage = document.getElementById("topHat");
hatImage.setAttribute("src", "rabbit-hat.gif");
var button = document.getElementById("hocusPocus");
button.setAttribute("value", "Get back in that hat!");
button.onclick = hideRabbit;
}
function hideRabbit() {
var hatImage = document.getElementById("topHat");
hatImage.setAttribute("src", "topHat.gif");
var button = document.getElementById("hocusPocus");
button.setAttribute("value", "Hocus Pocus!");
button.onclick = showRabbit;
}
</script>
</head>
<body>
<h1 align="center">Welcome to the DOM Magic Shop!</h1>
<form name="magic-hat">
<p align="center">
<img src="topHat.gif" id="topHat" />
<br /><br />
<input type="button" value="Hocus Pocus!" id="hocusPocus"
onClick="showRabbit();" />
</p>
</form>
</body>
</html>
|
這樣就得到了一個(gè)完成的、可以使用的 DOM 應用程序。自己試試吧!
結束語(yǔ)
現在您應該非常熟悉 DOM 了。前面的文章介紹了使用 DOM 所涉及到的基本概念,詳細地討論了 API,現在又建立一個(gè)簡(jiǎn)單的基于 DOM 的應用程序。一定要花點(diǎn)時(shí)間仔細閱讀本文,并自己嘗試一下。
雖然這是專(zhuān)門(mén)討論文檔對象模型的系列文章的最后一期,但肯定還會(huì )看到其他關(guān)于 DOM 的文章。事實(shí)上,如果在 Ajax 和 JavaScript 世界中不使用 DOM 就很難做多少事,至少在一定程度上如此。無(wú)論要創(chuàng )建復雜的突出顯示還是移動(dòng)效果,或者僅僅處理文本塊或圖片,DOM 都提供了一種非常簡(jiǎn)單易用的訪(fǎng)問(wèn) Web 頁(yè)面的方式。
如果對如何使用 DOM 仍然感覺(jué)沒(méi)有把握,花點(diǎn)時(shí)間溫習一下這三篇文章;本系列的其他文章在使用 DOM 的時(shí)候不再多作解釋?zhuān)x者也不希望迷失在這些細節之中而忽略關(guān)于其他概念的重要信息,比如 XML 和 JSON。為了保證能夠熟練地使用 DOM,自己編寫(xiě)幾個(gè)基于 DOM 的應用程序試試,這樣就很容易理解后面將要討論的一些數據格式問(wèn)題了。
下載
| 描述 |
名字 |
大小 |
下載方法 |
| 僅下載示例中的圖形 |
wa-ajaxintro6/ajax_6-images_download.zip |
91 KB |
HTTP |
| 完整的示例,包括 HTML 和圖形 |
wa-ajaxintro6/ajax_6-complete_examples.zip |
93 KB |
HTTP |
參考資料
學(xué)習
獲得產(chǎn)品和技術(shù)
討論
關(guān)于作者
|
|
|
|
Brett McLaughlin 從 Logo 時(shí)代就開(kāi)始使用計算機了。(還記得那個(gè)小三角嗎?)近年來(lái),他已經(jīng)成為 Java 和 XML 社區中最受歡迎的作者和程序員之一了。他曾經(jīng)在 Nextel Communications 實(shí)現過(guò)復雜的企業(yè)系統,在 Lutris Technologies 編寫(xiě)過(guò)應用服務(wù)器,最近在 O‘Reilly Media, Inc. 繼續撰寫(xiě)和編輯這方面的圖書(shū)。Brett 最新的著(zhù)作 Head Rush Ajax,為 Ajax 帶來(lái)了獲獎的創(chuàng )新 Head First 方法。他的近作 Java 1.5 Tiger: A Developer‘s Notebook 是關(guān)于這一 Java 技術(shù)最新版本的第一部專(zhuān)著(zhù)。經(jīng)典作品 Java and XML 仍然是在 Java 語(yǔ)言中使用 XML 技術(shù)的權威著(zhù)作之一。
|
|