五年前,如果不知道 XML,您就是一只無(wú)人重視的丑小鴨。十八個(gè)月前,Ruby 成了關(guān)注的中心,不知道 Ruby 的程序員只能坐冷板凳了。今天,如果想跟上最新的技術(shù)時(shí)尚,那您的目標就是 Ajax。
但是,Ajax 不僅僅 是一種時(shí)尚,它是一種構建網(wǎng)站的強大方法,而且不像學(xué)習一種全新的語(yǔ)言那樣困難。
但在詳細探討 Ajax 是什么之前,先讓我們花幾分鐘了解 Ajax 做 什么。目前,編寫(xiě)應用程序時(shí)有兩種基本的選擇:
兩者是類(lèi)似的,桌面應用程序通常以 CD 為介質(zhì)(有時(shí)候可從網(wǎng)站下載)并完全安裝到您的計算機上。桌面應用程序可能使用互聯(lián)網(wǎng)下載更新,但運行這些應用程序的代碼在桌面計算機上。Web 應用程序運行在某處的 Web 服務(wù)器上 —— 毫不奇怪,要通過(guò) Web 瀏覽器訪(fǎng)問(wèn)這種應用程序。
不過(guò),比這些應用程序的運行代碼放在何處更重要的是,應用程序如何運轉以及如何與其進(jìn)行交互。桌面應用程序一般很快(就在您的計算機上運行,不用等待互聯(lián)網(wǎng)連接),具有漂亮的用戶(hù)界面(通常和操作系統有關(guān))和非凡的動(dòng)態(tài)性??梢詥螕?、選擇、輸入、打開(kāi)菜單和子菜單、到處巡游,基本上不需要等待。
另一方面,Web 應用程序是最新的潮流,它們提供了在桌面上不能實(shí)現的服務(wù)(比如 Amazon.com 和 eBay)。但是,伴隨著(zhù) Web 的強大而出現的是等待,等待服務(wù)器響應,等待屏幕刷新,等待請求返回和生成新的頁(yè)面。
顯然這樣說(shuō)過(guò)于簡(jiǎn)略了,但基本的概念就是如此。您可能已經(jīng)猜到,Ajax 嘗試建立桌面應用程序的功能和交互性,與不斷更新的 Web 應用程序之間的橋梁??梢允褂孟褡烂鎽贸绦蛑谐R?jiàn)的動(dòng)態(tài)用戶(hù)界面和漂亮的控件,不過(guò)是在 Web 應用程序中。
還等什么呢?我們來(lái)看看 Ajax 如何將笨拙的 Web 界面轉化成能迅速響應的 Ajax 應用程序吧。
在談到 Ajax 時(shí),實(shí)際上涉及到多種技術(shù),要靈活地運用它必須深入了解這些不同的技術(shù)(本系列的頭幾篇文章將分別討論這些技術(shù))。好消息是您可能已經(jīng)非常熟悉其中的大部分技術(shù),更好的是這些技術(shù)都很容易學(xué)習,并不像完整的編程語(yǔ)言(如 Java 或 Ruby)那樣困難。
![]() |
|
下面是 Ajax 應用程序所用到的基本技術(shù):
div、span 和其他動(dòng)態(tài) HTML 元素來(lái)標記 HTML。 我們來(lái)進(jìn)一步分析這些技術(shù)的職責。以后的文章中我將深入討論這些技術(shù),目前只要熟悉這些組件和技術(shù)就可以了。對這些代碼越熟悉,就越容易從對這些技術(shù)的零散了解轉變到真正把握這些技術(shù)(同時(shí)也真正打開(kāi)了 Web 應用程序開(kāi)發(fā)的大門(mén))。
要了解的一個(gè)對象可能對您來(lái)說(shuō)也是最陌生的,即 XMLHttpRequest。這是一個(gè) JavaScript 對象,創(chuàng )建該對象很簡(jiǎn)單,如清單 1 所示。
|
下一期文章中將進(jìn)一步討論這個(gè)對象,現在要知道這是處理所有服務(wù)器通信的對象。繼續閱讀之前,先停下來(lái)想一想:通過(guò) XMLHttpRequest 對象與服務(wù)器進(jìn)行對話(huà)的是 JavaScript 技術(shù)。這不是一般的應用程序流,這恰恰是 Ajax 的強大功能的來(lái)源。
在一般的 Web 應用程序中,用戶(hù)填寫(xiě)表單字段并單擊 Submit 按鈕。然后整個(gè)表單發(fā)送到服務(wù)器,服務(wù)器將它轉發(fā)給處理表單的腳本(通常是 PHP 或 Java,也可能是 CGI 進(jìn)程或者類(lèi)似的東西),腳本執行完成后再發(fā)送回全新的頁(yè)面。該頁(yè)面可能是帶有已經(jīng)填充某些數據的新表單的 HTML,也可能是確認頁(yè)面,或者是具有根據原來(lái)表單中輸入數據選擇的某些選項的頁(yè)面。當然,在服務(wù)器上的腳本或程序處理和返回新表單時(shí)用戶(hù)必須等待。屏幕變成一片空白,等到服務(wù)器返回數據后再重新繪制。這就是交互性差的原因,用戶(hù)得不到立即反饋,因此感覺(jué)不同于桌面應用程序。
Ajax 基本上就是把 JavaScript 技術(shù)和 XMLHttpRequest 對象放在 Web 表單和服務(wù)器之間。當用戶(hù)填寫(xiě)表單時(shí),數據發(fā)送給一些 JavaScript 代碼而不是 直接發(fā)送給服務(wù)器。相反,JavaScript 代碼捕獲表單數據并向服務(wù)器發(fā)送請求。同時(shí)用戶(hù)屏幕上的表單也不會(huì )閃爍、消失或延遲。換句話(huà)說(shuō),JavaScript 代碼在幕后發(fā)送請求,用戶(hù)甚至不知道請求的發(fā)出。更好的是,請求是異步發(fā)送的,就是說(shuō) JavaScript 代碼(和用戶(hù))不用等待服務(wù)器的響應。因此用戶(hù)可以繼續輸入數據、滾動(dòng)屏幕和使用應用程序。
然后,服務(wù)器將數據返回 JavaScript 代碼(仍然在 Web 表單中),后者決定如何處理這些數據。它可以迅速更新表單數據,讓人感覺(jué)應用程序是立即完成的,表單沒(méi)有提交或刷新而用戶(hù)得到了新數據。JavaScript 代碼甚至可以對收到的數據執行某種計算,再發(fā)送另一個(gè)請求,完全不需要用戶(hù)干預!這就是 XMLHttpRequest 的強大之處。它可以根據需要自行與服務(wù)器進(jìn)行交互,用戶(hù)甚至可以完全不知道幕后發(fā)生的一切。結果就是類(lèi)似于桌面應用程序的動(dòng)態(tài)、快速響應、高交互性的體驗,但是背后又擁有互聯(lián)網(wǎng)的全部強大力量。
得到 XMLHttpRequest 的句柄后,其他的 JavaScript 代碼就非常簡(jiǎn)單了。事實(shí)上,我們將使用 JavaScript 代碼完成非?;镜娜蝿?wù):
對于前兩點(diǎn),需要非常熟悉 getElementById() 方法,如 清單 2 所示。
|
這里沒(méi)有特別需要注意的地方,真是好極了!您應該認識到這里并沒(méi)有非常復雜的東西。只要掌握了 XMLHttpRequest,Ajax 應用程序的其他部分就是如 清單 2 所示的簡(jiǎn)單 JavaScript 代碼了,混合有少量的 HTML。同時(shí),還要用一點(diǎn)兒 DOM,我們就來(lái)看看吧。
最后還有 DOM,即文檔對象模型??赡軐τ行┳x者來(lái)說(shuō) DOM 有點(diǎn)兒令人生畏,HTML 設計者很少使用它,即使 JavaScript 程序員也不大用到它,除非要完成某項高端編程任務(wù)。大量使用 DOM 的是 復雜的 Java 和 C/C++ 程序,這可能就是 DOM 被認為難以學(xué)習的原因。
幸運的是,在 JavaScript 技術(shù)中使用 DOM 很容易,也非常直觀(guān)?,F在,按照常規也許應該說(shuō)明如何使用 DOM,或者至少要給出一些示例代碼,但這樣做也可能誤導您。即使不理會(huì ) DOM,仍然能深入地探討 Ajax,這也是我準備采用的方法。以后的文章將再次討論 DOM,現在只要知道可能需要 DOM 就可以了。當需要在 JavaScript 代碼和服務(wù)器之間傳遞 XML 和改變 HTML 表單的時(shí)候,我們再深入研究 DOM。沒(méi)有它也能做一些有趣的工作,因此現在就把 DOM 放到一邊吧。
![]() ![]() |
![]()
|
有了上面的基礎知識后,我們來(lái)看看一些具體的例子。XMLHttpRequest 是 Ajax 應用程序的核心,而且對很多讀者來(lái)說(shuō)可能還比較陌生,我們就從這里開(kāi)始吧。從 清單 1 可以看出,創(chuàng )建和使用這個(gè)對象非常簡(jiǎn)單,不是嗎?等一等。
還記得幾年前的那些討厭的瀏覽器戰爭嗎?沒(méi)有一樣東西在不同的瀏覽器上得到同樣的結果。不管您是否相信,這些戰爭仍然在繼續,雖然規模較小。但令人奇怪的是,XMLHttpRequest 成了這場(chǎng)戰爭的犧牲品之一。因此獲得 XMLHttpRequest 對象可能需要采用不同的方法。下面我將詳細地進(jìn)行解釋。
Microsoft 瀏覽器 Internet Explorer 使用 MSXML 解析器處理 XML(可以通過(guò) 參考資料 進(jìn)一步了解 MSXML)。因此如果編寫(xiě)的 Ajax 應用程序要和 Internet Explorer 打交道,那么必須用一種特殊的方式創(chuàng )建對象。
但并不是這么簡(jiǎn)單。根據 Internet Explorer 中安裝的 JavaScript 技術(shù)版本不同,MSXML 實(shí)際上有兩種不同的版本,因此必須對這兩種情況分別編寫(xiě)代碼。請參閱 清單 3,其中的代碼在 Microsoft 瀏覽器上創(chuàng )建了一個(gè) XMLHttpRequest。
|
您對這些代碼可能還不完全理解,但沒(méi)有關(guān)系。當本系列文章結束的時(shí)候,您將對 JavaScript 編程、錯誤處理、條件編譯等有更深的了解?,F在只要牢牢記住其中的兩行代碼:
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
和
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");。
這兩行代碼基本上就是嘗試使用一個(gè)版本的 MSXML 創(chuàng )建對象,如果失敗則使用另一個(gè)版本創(chuàng )建該對象。不錯吧?如果都不成功,則將 xmlHttp 變量設為 false,告訴您的代碼出現了問(wèn)題。如果出現這種情況,可能是因為安裝了非 Microsoft 瀏覽器,需要使用不同的代碼。
如果選擇的瀏覽器不是 Internet Explorer,或者為非 Microsoft 瀏覽器編寫(xiě)代碼,就需要使用不同的代碼。事實(shí)上就是 清單 1 所示的一行簡(jiǎn)單代碼:
var xmlHttp = new XMLHttpRequest object;。
這行簡(jiǎn)單得多的代碼在 Mozilla、Firefox、Safari、Opera 以及基本上所有以任何形式或方式支持 Ajax 的非 Microsoft 瀏覽器中,創(chuàng )建了 XMLHttpRequest 對象。
關(guān)鍵是要支持所有 瀏覽器。誰(shuí)愿意編寫(xiě)一個(gè)只能用于 Internet Explorer 或者非 Microsoft 瀏覽器的應用程序呢?或者更糟,要編寫(xiě)一個(gè)應用程序兩次?當然不!因此代碼要同時(shí)支持 Internet Explorer 和非 Microsoft 瀏覽器。清單 4 顯示了這樣的代碼。
|
現在先不管那些注釋掉的奇怪符號,如 @cc_on,這是特殊的 JavaScript 編譯器命令,將在下一期針對 XMLHttpRequest 的文章中詳細討論。這段代碼的核心分為三步:
xmlHttp 來(lái)引用即將創(chuàng )建的 XMLHttpRequest 對象。 Msxml2.XMLHTTP 對象創(chuàng )建它。 Microsoft.XMLHTTP 對象。 xmlHttp,則以非 Microsoft 的方式創(chuàng )建該對象。 最后,xmlHttp 應該引用一個(gè)有效的 XMLHttpRequest 對象,無(wú)論運行什么樣的瀏覽器。
安全性如何呢?現在瀏覽器允許用戶(hù)提高他們的安全等級,關(guān)閉 JavaScript 技術(shù),禁用瀏覽器中的任何選項。在這種情況下,代碼無(wú)論如何都不會(huì )工作。此時(shí)必須適當地處理問(wèn)題,這需要單獨的一篇文章來(lái)討論,要放到以后了(這個(gè)系列夠長(cháng)了吧?不用擔心,讀完之前也許您就掌握了)?,F在要編寫(xiě)一段健壯但不夠完美的代碼,對于掌握 Ajax 來(lái)說(shuō)就很好了。以后我們還將討論更多的細節。
![]() ![]() |
![]()
|
現在我們介紹了 Ajax,對 XMLHttpRequest 對象以及如何創(chuàng )建它也有了基本的了解。如果閱讀得很仔細,您可能已經(jīng)知道與服務(wù)器上的 Web 應用程序打交道的是 JavaScript 技術(shù),而不是直接提交給那個(gè)應用程序的 HTML 表單。
還缺少什么呢?到底如何使用 XMLHttpRequest。因為這段代碼非常重要,您編寫(xiě)的每個(gè) Ajax 應用程序都要以某種形式使用它,先看看 Ajax 的基本請求/響應模型是什么樣吧。
您已經(jīng)有了一個(gè)嶄新的 XMLHttpRequest 對象,現在讓它干點(diǎn)活兒吧。首先需要一個(gè) Web 頁(yè)面能夠調用的 JavaScript 方法(比如當用戶(hù)輸入文本或者從菜單中選擇一項時(shí))。接下來(lái)就是在所有 Ajax 應用程序中基本都雷同的流程:
清單 5 中的示例 Ajax 方法就是按照這個(gè)順序組織的:
|
其中大部分代碼意義都很明確。開(kāi)始的代碼使用基本 JavaScript 代碼獲取幾個(gè)表單字段的值。然后設置一個(gè) PHP 腳本作為鏈接的目標。要注意腳本 URL 的指定方式,city 和 state(來(lái)自表單)使用簡(jiǎn)單的 GET 參數附加在 URL 之后。
然后打開(kāi)一個(gè)連接,這是您第一次看到使用 XMLHttpRequest。其中指定了連接方法(GET)和要連接的 URL。最后一個(gè)參數如果設為 true,那么將請求一個(gè)異步連接(這就是 Ajax 的由來(lái))。如果使用 false,那么代碼發(fā)出請求后將等待服務(wù)器返回的響應。如果設為 true,當服務(wù)器在后臺處理請求的時(shí)候用戶(hù)仍然可以使用表單(甚至調用其他 JavaScript 方法)。
xmlHttp(要記住,這是 XMLHttpRequest 對象實(shí)例)的 onreadystatechange 屬性可以告訴服務(wù)器在運行完成 后(可能要用五分鐘或者五個(gè)小時(shí))做什么。因為代碼沒(méi)有等待服務(wù)器,必須讓服務(wù)器知道怎么做以便您能作出響應。在這個(gè)示例中,如果服務(wù)器處理完了請求,一個(gè)特殊的名為 updatePage() 的方法將被觸發(fā)。
最后,使用值 null 調用 send()。因為已經(jīng)在請求 URL 中添加了要發(fā)送給服務(wù)器的數據(city 和 state),所以請求中不需要發(fā)送任何數據。這樣就發(fā)出了請求,服務(wù)器按照您的要求工作。
如果沒(méi)有發(fā)現任何新鮮的東西,您應該體會(huì )到這是多么簡(jiǎn)單明了!除了牢牢記住 Ajax 的異步特性外,這些內容都相當簡(jiǎn)單。應該感激 Ajax 使您能夠專(zhuān)心編寫(xiě)漂亮的應用程序和界面,而不用擔心復雜的 HTTP 請求/響應代碼。
清單 5 中的代碼說(shuō)明了 Ajax 的易用性。數據是簡(jiǎn)單的文本,可以作為請求 URL 的一部分。用 GET 而不是更復雜的 POST 發(fā)送請求。沒(méi)有 XML 和要添加的內容頭部,請求體中沒(méi)有要發(fā)送的數據;換句話(huà)說(shuō),這就是 Ajax 的烏托邦。
不用擔心,隨著(zhù)本系列文章的展開(kāi),事情會(huì )變得越來(lái)越復雜。您將看到如何發(fā)送 POST 請求、如何設置請求頭部和內容類(lèi)型、如何在消息中編碼 XML、如何增加請求的安全性,可以做的工作還有很多!暫時(shí)先不用管那些難點(diǎn),掌握好基本的東西就行了,很快我們就會(huì )建立一整套的 Ajax 工具庫。
現在要面對服務(wù)器的響應了?,F在只要知道兩點(diǎn):
xmlHttp.readyState 屬性的值等于 4。 xmlHttp.responseText 屬性中。 其中的第一點(diǎn),即就緒狀態(tài),將在下一篇文章中詳細討論,您將進(jìn)一步了解 HTTP 請求的階段,可能比您設想的還多?,F在只要檢查一個(gè)特定的值(4)就可以了(下一期文章中還有更多的值要介紹)。第二點(diǎn),使用 xmlHttp.responseText 屬性獲得服務(wù)器的響應,這很簡(jiǎn)單。清單 6 中的示例方法可供服務(wù)器根據 清單 5 中發(fā)送的數據調用。
|
這些代碼同樣既不難也不復雜。它等待服務(wù)器調用,如果是就緒狀態(tài),則使用服務(wù)器返回的值(這里是用戶(hù)輸入的城市和州的 ZIP 編碼)設置另一個(gè)表單字段的值。于是包含 ZIP 編碼的 zipCode 字段突然出現了,而用戶(hù)沒(méi)有按任何按鈕!這就是前面所說(shuō)的桌面應用程序的感覺(jué)??焖夙憫?、動(dòng)態(tài)感受等等,這些都只因為有了小小的一段 Ajax 代碼。
細心的讀者可能注意到 zipCode 是一個(gè)普通的文本字段。一旦服務(wù)器返回 ZIP 編碼,updatePage() 方法就用城市/州的 ZIP 編碼設置那個(gè)字段的值,用戶(hù)就可以改寫(xiě)該值。這樣做有兩個(gè)原因:保持例子簡(jiǎn)單,說(shuō)明有時(shí)候可能希望 用戶(hù)能夠修改服務(wù)器返回的數據。要記住這兩點(diǎn),它們對于好的用戶(hù)界面設計來(lái)說(shuō)很重要。
![]() ![]() |
![]()
|
還有什么呢?實(shí)際上沒(méi)有多少了。一個(gè) JavaScript 方法捕捉用戶(hù)輸入表單的信息并將其發(fā)送到服務(wù)器,另一個(gè) JavaScript 方法監聽(tīng)和處理響應,并在響應返回時(shí)設置字段的值。所有這些實(shí)際上都依賴(lài)于調用 第一個(gè) JavaScript 方法,它啟動(dòng)了整個(gè)過(guò)程。最明顯的辦法是在 HTML 表單中增加一個(gè)按鈕,但這是 2001 年的辦法,您不這樣認為嗎?還是像 清單 7 這樣利用 JavaScript 技術(shù)吧。
|
如果感覺(jué)這像是一段相當普通的代碼,那就對了,正是如此!當用戶(hù)在 city 或 state 字段中輸入新的值時(shí),callServer() 方法就被觸發(fā),于是 Ajax 開(kāi)始運行了。有點(diǎn)兒明白怎么回事了吧?好,就是如此!
![]() ![]() |
![]()
|
現在您可能已經(jīng)準備開(kāi)始編寫(xiě)第一個(gè) Ajax 應用程序了,至少也希望認真讀一下 參考資料 中的那些文章了吧?但可以首先從這些應用程序如何工作的基本概念開(kāi)始,對 XMLHttpRequest 對象有基本的了解。在下一期文章中,您將掌握這個(gè)對象,學(xué)會(huì )如何處理 JavaScript 和服務(wù)器的通信、如何使用 HTML 表單以及如何獲得 DOM 句柄。
現在先花點(diǎn)兒時(shí)間考慮考慮 Ajax 應用程序有多么強大。設想一下,當單擊按鈕、輸入一個(gè)字段、從組合框中選擇一個(gè)選項或者用鼠標在屏幕上拖動(dòng)時(shí),Web 表單能夠立刻作出響應會(huì )是什么情形。想一想異步 究竟意味著(zhù)什么,想一想 JavaScript 代碼運行而且不等待 服務(wù)器對它的請求作出響應。會(huì )遇到什么樣的問(wèn)題?會(huì )進(jìn)入什么樣的領(lǐng)域?考慮到這種新的方法,編程的時(shí)候應如何改變表單的設計?
如果在這些問(wèn)題上花一點(diǎn)兒時(shí)間,與簡(jiǎn)單地剪切/粘貼某些代碼到您根本不理解的應用程序中相比,收益會(huì )更多。在下一期文章中,我們將把這些概念付諸實(shí)踐,詳細介紹使應用程序按照這種方式工作所需要的代碼。因此,現在先享受一下 Ajax 所帶來(lái)的可能性吧。
![]() ![]() |
![]()
|
XMLHttpRequest 對象,請閱讀 關(guān)于 XMLHttpRequest 對象的這篇文章。 聯(lián)系客服