怎樣使用AJAX進(jìn)行應用程序開(kāi)發(fā)
閱讀提要 AJAX,一個(gè)
異步JavaScript和XML的縮略詞,是當今快速發(fā)展的Web開(kāi)發(fā)界十分熱門(mén)的技術(shù)。在這項新技術(shù)提供巨大能力的同時(shí),它也燃發(fā)了在"Back"按鈕問(wèn)題上的不容置疑的爭論。本文作者將向你解釋怎樣在真實(shí)世界中使用AJAX以及怎樣在一個(gè)工程中評估它的價(jià)值。在你讀完本文后,你就會(huì )明白什么是AJAX,在什么情況下,為什么以及怎樣使用這項技術(shù)。
一、 簡(jiǎn)介 AJAX,一個(gè)異步JavaScript和XML的縮略詞,是最近出來(lái)的技術(shù)詞語(yǔ)。異步意味著(zhù)你可以經(jīng)由超文本傳輸協(xié)議(HTTP)向一個(gè)服務(wù)器發(fā)出請求并且
在等待該響應時(shí)繼續處理另外的數據。這就意味著(zhù),例如,你可以調用一個(gè)服務(wù)器端腳本來(lái)從一個(gè)數據庫中以XML方式檢索數據,把數據發(fā)送到存儲在一個(gè)數據庫的服務(wù)器腳本,或者簡(jiǎn)單地裝載一個(gè)XML文件以填充你的Web站點(diǎn)而不需刷新該頁(yè)面。然而,在這項新技術(shù)提供巨大能力的同時(shí),它也引起了在"Back"按鈕問(wèn)題上的很多爭論。本文將幫助你確定在真實(shí)世界中何時(shí)使用AJAX是最佳選擇。
首先,我假定你對縮略詞JavaScript和XML部分有一個(gè)基本了解。盡管你能通過(guò)AJAX請求任何類(lèi)型的
文本文件,但是我在此主要集中討論XML。我將解釋怎樣在真實(shí)世界中使用AJAX以及怎樣在一個(gè)工程中評估它的價(jià)值。在你讀完本文后,你將會(huì )明白什么是AJAX,在什么情況下,為什么以及怎樣使用這項技術(shù)。你將要學(xué)習,在保持給用戶(hù)提供直觀(guān)體驗的同時(shí)怎樣創(chuàng )建對象,發(fā)出請求以及定制響應。
我已創(chuàng )建了一個(gè)適合于本文的示例工程(你可以下載源代碼)。這個(gè)示例實(shí)現了一個(gè)簡(jiǎn)單的請求-它裝載一個(gè)包含頁(yè)面內容的XML文件并且分析數據以把它顯示在一個(gè)HTML頁(yè)面中。
二、 常規屬性和方法 表1和2提供了一個(gè)屬性和方法的概述-它們?yōu)閃indows Internet Explorer 5,Mozilla,Netscape 7,Safari 1.2,和Opera等瀏覽器所支持。
表1屬性
| 屬性 | 描述 |
| onreadystatechange | 當請求對象變化時(shí)該事件處理器激活。 |
| readyState | 返回指示對象的當前狀態(tài)的值。 |
| responseText | 來(lái)自服務(wù)器的響應串的版本。 |
| responseXML | 來(lái)自服務(wù)器的響應的DOM兼容的文檔對象。 |
| status | 來(lái)自服務(wù)器的響應的狀態(tài)碼。 |
| statusText | 以一個(gè)字符串形式返回的狀態(tài)消息。 |
表2方法
| 方法 | 描述 |
| Abort() | 取消當前HTTP請求。 |
| getAllResponseHeaders() | 檢索所有的HTTP頭值。 |
| getResponseHeader("headerLabel") | 從響應體中檢索一個(gè)HTTP頭部的值。 |
| open("method","URL"[,asyncFlag[,"userName"[,"password"]]]) | 初始化一個(gè)MSXML2.XMLHTTP請求,并從該請求指定方法,URL和認證信息。 |
| send(content) | 發(fā)送一個(gè)HTTP請求到服務(wù)器并接收響應。 |
| setRequestHeader("label", "value") | 指定一個(gè)HTTP頭的名字。 |
三、 從哪里開(kāi)始 首先,你需要創(chuàng )建XML文件-后面我們對之進(jìn)行請求并作為頁(yè)面內容進(jìn)行分析。你正在請求的文件必須與目標工程駐留在相同的服務(wù)器上。
下一步,創(chuàng )建發(fā)出請求的HTML文件。當頁(yè)面通過(guò)使用頁(yè)面主體中的onload方法進(jìn)行加載時(shí),該請求發(fā)生。接著(zhù),該文件需要一個(gè)有ID的div標簽,這樣當我們準備好要顯示內容時(shí)就可以對之進(jìn)行定位。當你做完所有這些,你的頁(yè)面的主體看上去如下:
<body onload="makeRequest(‘xml/content.xml‘);"> <div id="copy"></div> </body> |
四、 創(chuàng )建請求對象 為了創(chuàng )建請求對象,你必須檢查是否瀏覽器使用XMLHttpRequest或ActiveXObject。這兩個(gè)對象之間的主要區別在于使用它們的瀏覽器。Windows IE 5 及以上版本使用ActiveX對象;而Mozilla,Netscape 7,Opera和Safari 1.2及以上版本使用XMLHttpRequest對象。另外一個(gè)區別是你創(chuàng )建對象的方式:Opera,Mozilla,Netscape和Safari允許你簡(jiǎn)單地調用該對象的構造器,但是Windows IE需要把對象的名字傳遞到ActiveX構造器中。下面是怎樣創(chuàng )建代碼來(lái)決定要使用哪個(gè)對象和怎樣創(chuàng )建它的示例:
if(window.XMLHttpRequest) { request = new XMLHttpRequest();} else if(window.ActiveXObject) { request = new ActiveXObject("MSXML2.XMLHTTP");} |
五、 發(fā)出請求
現在既然你已經(jīng)創(chuàng )建了你的請求對象,那么你已經(jīng)為向服務(wù)器發(fā)出請求作了準備。創(chuàng )建一個(gè)到事件處理器的參考以聽(tīng)取onreadystatechange事件。然后,該事件處理器方法將在狀態(tài)發(fā)生變化時(shí)作出響應。一旦我們完成請求,我們就開(kāi)始創(chuàng )建這個(gè)方法。打開(kāi)連接以GET或POST一個(gè)定制的URL-在此是一個(gè)content.xml,并且設置一個(gè)布爾定義-是否你想要進(jìn)行異步調用。
現在到了發(fā)出請求的時(shí)間了。在這個(gè)示例中,我使用了null,因為我們使用的是GET;為了使用POST,你需要使用下面這個(gè)方法發(fā)出一個(gè)查詢(xún)串:
request.onreadystatechange = onResponse; request.open("GET". url, true); request.send(null); |
六、 定制加載和錯誤處理消息 你為onreadystatechange方法創(chuàng )建的事件處理器正是集中進(jìn)行加載和處理錯誤的場(chǎng)所?,F在到了考慮用戶(hù)并針對他們與之交互的內容的狀態(tài)提供反饋的時(shí)候了。在這個(gè)實(shí)例中,我針對所有的裝載狀態(tài)代碼提供反饋,并且也對最經(jīng)常發(fā)生的錯誤處理狀態(tài)代碼提供一些基本的反饋。為了顯示請求對象的當前狀態(tài),readyState屬性包括顯示在下表中的一些值。
| 值 | 描述 |
| 0 | 未初始化,對象沒(méi)有用數據進(jìn)行初始化。 |
| 1 | 裝載中,對象正在裝載它的數據。 |
| 2 | 裝載結束,對象完成了它的數據的裝載。 |
| 3 | 可交互,用戶(hù)能與對象交互了,盡管它還沒(méi)有裝載結束。 |
| 4 | 完成,對象已經(jīng)完全被初始化。 |
W3C中有很長(cháng)的一串有關(guān)HTTP狀態(tài)代碼的定義。我選擇了兩個(gè)狀態(tài)代碼:
·200:請求成功了。
·404:服務(wù)器沒(méi)有找到與所請求的文件相匹配的任何東西。
最后,我檢查任何另外的狀況代碼-它們將生成一個(gè)錯誤并提供一個(gè)一般錯誤信息。下面是一個(gè)代碼示例-你可以用之來(lái)處理這些情況。注意,我在定位我們前面在HTML文件的主體中創(chuàng )建的div ID并且對它應用裝載和/或錯誤信息-通過(guò)innerHTML方法-這個(gè)方法用于設置在div對象的開(kāi)始和結束標簽之間的HTML:
if(obj.readyState == 0) { document.getElementById(‘copy‘).innerHTML = "Sending Request...";} if(obj.readyState == 1) { document.getElementById(‘copy‘).innerHTML = "Loading Response...";} if(obj.readyState == 2) { document.getElementById(‘copy‘).innerHTML = "Response Loaded...";} if(obj.readyState == 3) { document.getElementById(‘copy‘).innerHTML = "Response Ready...";} if(obj.readyState == 4){ if(obj.status == 200){ return true; } else if(obj.status == 404) { // 添加一個(gè)定制消息或把用戶(hù)重定向到另外一個(gè)頁(yè)面 document.getElementById(‘copy‘).innerHTML = "File not found"; } else {document.getElementById(‘copy‘).innerHTML = "There was a problem retrieving the XML."; } } |
當狀況代碼為200時(shí),這意味著(zhù)請求成功。下面開(kāi)始進(jìn)行響應了。
七、分析響應 當你準備好分析來(lái)自請求對象的響應時(shí),真正的工作開(kāi)始了?,F在你可以用你請求的數據開(kāi)始工作。僅為測試目的,在開(kāi)發(fā)期間,可以使用responseText和responseXML屬性來(lái)顯示來(lái)自響應的原始數據。為了存取XML響應中的結點(diǎn),首先使用你創(chuàng )建的請求對象,定位到responseXML屬性以檢索(你可能已經(jīng)猜測出來(lái))來(lái)自響應的XML。定位到documentElement-它檢索一個(gè)到XML響應的根結點(diǎn)的參考。
| var response = request.responseXML.documentElement; |
現在既然你有了到響應的根結點(diǎn)的參考,那么你可以使用getElementsByTagName()以結點(diǎn)名字來(lái)檢索childNodes。下面一行用一個(gè)頭部的nodeName來(lái)定位一個(gè)childNode:
| response.getElementsByTagName(‘header‘)[0].firstChild.data; |
使用firstChild.data可以允許你存取該元素中的文本:
| response.getElementsByTagName(‘header‘)[0].firstChild.data; |
下面是怎樣創(chuàng )建這些代碼的完整的例子:
var response = request.responseXML.documentElement; var header = response.getElementsByTagName(‘header‘)[0].firstChild.data; document.getElementById(‘copy‘).innerHTML = header; |
八、需求分析 現在既然你知道怎樣使用AJAX的基礎知識,那么下一步就是決定是否在一工程使用它。須記住的最重要的事情是,在你還沒(méi)有刷新頁(yè)面時(shí)你無(wú)法使用"Back"按鈕。為此,可以先專(zhuān)注于你的工程中的一小部分-它能夠從使用這種類(lèi)型的交互中受益。例如,你可以創(chuàng )建一個(gè)表單-它在用戶(hù)每次輸入一個(gè)輸入字段或一個(gè)字母時(shí)查詢(xún)一個(gè)腳本以便進(jìn)行實(shí)時(shí)校驗。你可以創(chuàng )建一個(gè)拖放頁(yè)面-在釋放一項時(shí),它能夠把數據發(fā)送到一個(gè)腳本中并把該頁(yè)面的狀態(tài)保存到一個(gè)數據庫中。使用AJAX的理由毫無(wú)疑問(wèn)是存在的;并且這種使用無(wú)論對開(kāi)發(fā)者還是用戶(hù)都會(huì )帶來(lái)益處;這全依賴(lài)于具體的條件和執行情況。
還有其它方法可用來(lái)解決"Back"按鈕的問(wèn)題,例如使用Google Gmail-它現在能夠為你的操作提供一種撤消功能而不刷新該頁(yè)面。以后還會(huì )出現許多更具創(chuàng )造性的例子-它們將通過(guò)提供給開(kāi)發(fā)者創(chuàng )建獨特實(shí)時(shí)的體驗的手段給用戶(hù)帶來(lái)更大的好處。
九、結論 盡管AJAX允許我們構建新的和改進(jìn)的方式來(lái)與一個(gè)WEB頁(yè)面進(jìn)行交互;但是作為開(kāi)發(fā)者,我們需要牢記產(chǎn)品是不考慮技術(shù)的;它關(guān)心的是用戶(hù)以及其如何與用戶(hù)進(jìn)行交互。沒(méi)有了用戶(hù)群,我們構建的工程毫無(wú)用處?;谶@個(gè)標準,我們就能評估應該使用什么技術(shù)以及何時(shí)使用它們來(lái)創(chuàng )建對相應用戶(hù)有用的應用軟件。