IBM®
直接進入主要内容
    Taiwan  [選擇 ]      使用條款
 
 
    
     首頁      產品      服務與解决方案      技術支援與下載      個人專區     
直接進入主要内容

developerWorks 台灣  >  XML, SOA and Web services | Java technology  >

掌握 Ajax,第 1 部分: Ajax 簡介

理解 Ajax 及其工作原理,建置網站的一種有效方法

developerWorks
文件選項

需要JavaScript的文件選項無法顯示

討論



級別: 入門

Brett McLaughlin, 作家,編輯, O'Reilly and Associates

2006 年 1 月 04 日

Ajax 由 HTML、JavaScript™ 技術、DHTML 和 DOM 組成,這一傑出的方法可以將笨拙的 Web 介面轉化成互動性的 Ajax 應用程式。本文的作者是一位 Ajax 專家,他展示了這些技術如何協同工作 —— 從總體概述到細節的討論 —— 使高效率的 Web 開發成為現實。他還揭開了 Ajax 核心概念的神秘面紗,包括 XMLHttpRequest 物件。

五年前,如果不知道 XML,您就是一隻無人重視的醜小鴨。十八個月前,Ruby 成了關注的中心,不知道 Ruby 的程式師只能坐冷板凳了。今天,如果想跟上最新的技術時尚,那您的目標就是 Ajax。

但是,Ajax 不僅僅 是一種時尚,它是一種建置網站的強大方法,而且不像學習一種全新的語言那樣困難。

但在詳細探討 Ajax 是什麼之前,先讓我們花幾分鐘瞭解 Ajax 什麼。目前,設計應用程式時有兩種基本的選擇:

  • 視窗應用程式
  • Web 應用程式

兩者是類似的,視窗應用程式通常以 CD 為媒體(有時候可從網站下載)並完全安裝到您的電腦上。視窗應用程式可能使用網際網路下載更新,但執行這些應用程式的程式碼在視窗電腦上。Web 應用程式執行在某處的 Web 伺服器上 —— 毫不奇怪,要透過 Web 瀏覽器執行這種應用程式。

不過,比這些應用程式的執行程式碼放在何處更重要的是,應用程式如何執行以及如何與其進行互動。視窗應用程式一般很快(就在您的電腦上執行,不用等待網際網路連接),具有漂亮的使用者介面(通常和作業系統有關)和非凡的動態性。可以點選、選擇、輸入、打開功能表和子功能表、到處悠遊,基本上不需要等待。

另一方面,Web 應用程式是最新的潮流,它們提供了在視窗上不能實現的服務(比如 Amazon.com 和 eBay)。但是,伴隨著 Web 的好處而出現的是等待,等待伺服器反應,等待螢幕更新,等待請求返回和產生新的頁面。

顯然這樣說過於簡略了,但基本的概念就是如此。您可能已經猜到,Ajax 嘗試建立視窗應用程式的功能和互動性,與不斷更新的 Web 應用程式之間的橋樑。可以使用像桌面應用程式中常見的動態用戶介面和漂亮的控制項,不過是在 Web 應用程式中。

還等什麼呢?我們來看看 Ajax 如何將笨拙的 Web 介面轉化成能迅速回應的 Ajax 應用程式吧。

老技術,新技巧

在談到 Ajax 時,實際上涉及到多種技術,要靈活地運用它必須深入瞭解這些不同的技術(本系列的頭幾篇文章將分別討論這些技術)。好消息是您可能已經非常熟悉其中的大部分技術,更好的是這些技術都很容易學習,並不像完整的程式語言(如 Java 或 Ruby)那樣困難。

Ajax 的定義

順便說一下,Ajax 是 Asynchronous JavaScript and XML(以及 DHTML 等)的縮寫。這個縮寫是 Adaptive Path 的 Jesse James Garrett 發明的(請參閱 參考資料),按照 Jesse 的解釋,這不是 個首字母縮寫詞。

下面是 Ajax 應用程式所用到的基本技術:

  • HTML 用於建立 Web 表單並確認應用程式其他部分使用的欄位。
  • JavaScript 程式碼是執行 Ajax 應用程式的核心程式碼,幫助改進與伺服器應用程式的通訊。
  • DHTML 或 Dynamic HTML,用於動態更新表單。我們將使用 divspan 和其他動態 HTML 元素來標記 HTML。
  • 文件物件模型 DOM 用於(透過 JavaScript 程式碼)處理 HTML 結構和(某些情況下)伺服器返回的 XML。

我們來進一步分析這些技術的職責。以後的文章中我將深入討論這些技術,目前只要熟悉這些元件和技術就可以了。對這些程式碼越熟悉,就越容易從對這些技術的零散瞭解轉變到真正把握這些技術(同時也真正打開了 Web 應用程式開發的大門)。

XMLHttpRequest 對象

要瞭解的一個物件可能對您來說也是最陌生的,即 XMLHttpRequest。這是一個 JavaScript 物件,建立該物件很簡單,如清單 1 所示。


清單 1. 建立新的 XMLHttpRequest 物件


<script language="javascript" type="text/javascript">
var xmlHttp = new XMLHttpRequest();
</script>

下一期文章中將進一步討論這個物件,現在要知道這是處理所有伺服器通訊的物件。繼續閱讀之前,先停下來想一想:透過 XMLHttpRequest 物件與伺服器進行對話的是 JavaScript 技術。這不是一般的應用程式流,這恰恰是 Ajax 的強大功能的來源。

在一般的 Web 應用程式中,使用者填寫表單文字欄位並點選 Submit 按鈕。然後整個表單傳送到伺服器,伺服器將它轉傳給處理表單的腳本(通常是 PHP 或 Java,也可能是 CGI 程式或者類似的東西),腳本執行完成後再傳送回全新的頁面。該頁面可能是帶有已經填寫某些資料的新表單的 HTML,也可能是確認頁面,或者是具有根據原來表單中輸入資料選擇的某些選項的頁面。當然,在伺服器上的腳本或程式處理和返回新表單時使用者必須等待。螢幕變成一片空白,等到伺服器傳回資料後再重新繪製。這就是互動性差的原因,用戶得不到立即回饋,因此感覺不同於視窗應用程式。

Ajax 基本上就是把 JavaScript 技術和 XMLHttpRequest 物件放在 Web 表單和伺服器之間。當使用者填寫表單時,資料發送給一些 JavaScript 程式碼而不是 直接傳送給伺服器。相反,JavaScript 程式碼接獲表單數據並向伺服器發送請求。同時使用者螢幕上的表單也不會閃爍、消失或延遲。換句話說,JavaScript 程式碼在幕後傳送請求,使用者甚至不知道請求的發出。更好的是,請求是非同步傳送的,就是說 JavaScript 程式碼(和使用者)不用等待伺服器的回應。因此使用者可以繼續輸入資料、拉動螢幕和使用應用程式。

然後,伺服器將資料傳回 JavaScript 程式碼(仍然在 Web 表單中),後者決定如何處理這些資料。它可以迅速更新表單數據,讓人感覺應用程式是立即完成的,表單沒有提交或更新而使用者得到了新資料。JavaScript 程式碼甚至可以對收到的資料執行某種計算,再發送另一個請求,完全不需要用戶干預!這就是 XMLHttpRequest 的強大之處。它可以根據需要自行與伺服器進行互動,使用者甚至可以完全不知道幕後發生的一切。結果就是類似於桌面應用程式的動態、快速回應、高交互性的體驗,但是背後又擁有網際網路的完全強大力量。

加入一些 JavaScript

得到 XMLHttpRequest 的控制碼後,其他的 JavaScript 程式碼就非常簡單了。事實上,我們將使用 JavaScript 程式碼完成非常基本的任務:

  • 取得表單數據:JavaScript 程式碼很容易從 HTML 表單中取得資料並傳送到伺服器。
  • 修改表單上的資料:更新表單也很簡單,從設置欄位值到迅速替換圖像。
  • 解析 HTML 和 XML:使用 JavaScript 程式碼操縱 DOM(請參閱 下一節),處理 HTML 表單伺服器傳回的 XML 資料的結構。

對於前兩點,需要非常熟悉 getElementById() 方法,如 清單 2 所示。


清單 2. 用 JavaScript 程式碼獲取和設置欄位值


// Get the value of the "phone" field and stuff it in a variable called phone
var phone = document.getElementById("phone").value;

// Set some values on a form using an array called response
document.getElementById("order").value = response[0];
document.getElementById("address").value = response[1];

這裏沒有特別需要注意的地方,真是好極了!您應該認識到這裏並沒有非常複雜的東西。只要掌握了 XMLHttpRequest,Ajax 應用程式的其他部分就是如 清單 2 所示的簡單 JavaScript 程式碼了,混合有少量的 HTML。同時,還要用一點 DOM,我們就來看看吧。

以 DOM 結束

最後還有 DOM,即文件物件模型。可能對有些讀者來說 DOM 有點令人生畏,HTML 設計者很少使用它,即使 JavaScript 程式設計師也不大用到它,除非要完成某項高層程式設計任務。大量使用 DOM 的 複雜的 Java 和 C/C++ 程式,這可能就是 DOM 被認為難以學習的原因。

幸運的是,在 JavaScript 技術中使用 DOM 很容易,也非常直接。現在,按照常規也許應該說明如何使用 DOM,或者至少要給一些範例程式碼,但這樣做也可能誤導您。即使不理會 DOM,仍然能深入地探討 Ajax,這也是我準備採用的方法。以後的文章將再次討論 DOM,現在只要知道可能需要 DOM 就可以了。當需要在 JavaScript 程式碼和伺服器之間傳遞 XML 和改變 HTML 表單的時候,我們再深入研究 DOM。沒有它也能做一些有趣的工作,因此現在就把 DOM 放到一邊吧。



回到頂端


獲取 Request 對象

有了上面的基本知識後,我們來看看一些具體的例子。XMLHttpRequest 是 Ajax 應用程式的核心,而且對很多讀者來說可能還比較陌生,我們就從這裏開始吧。從 清單 1 可以看出,建立和使用這個物件非常簡單,不是嗎?等一等。

還記得幾年前的那些討厭的瀏覽器戰爭嗎?沒有一樣東西在不同的瀏覽器上得到同樣的結果。不管您是否相信,這些戰爭仍然在繼續,雖然規模較小。但令人奇怪的是,XMLHttpRequest 成了這場戰爭的犧牲品之一。因此獲得 XMLHttpRequest 物件可能需要採用不同的方法。下面我將詳細地進行解釋。

使用 Microsoft 瀏覽器

Microsoft 瀏覽器 Internet Explorer 使用 MSXML 解析器處理 XML(可以透過 參考資料 進一步瞭解 MSXML)。因此如果設計的 Ajax 應用程式要和 Internet Explorer 打交道,那麼必須用一種特殊的方式建立物件。

但並不是這麼簡單。根據 Internet Explorer 中安裝的 JavaScript 技術版本不同,MSXML 實際上有兩種不同的版本,因此必須對這兩種情況分別設計程式碼。請參閱 清單 3,其中的程式碼在 Microsoft 瀏覽器上建立了一個 XMLHttpRequest


清單 3. 在 Microsoft 流覽器上創建 XMLHttpRequest 對象


var xmlHttp = false;
try {
  xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
  try {
    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (e2) {
    xmlHttp = false;
  }
}

您對這些程式碼可能還不完全理解,但沒有關係。當本系列文章結束的時候,將對 JavaScript 程式設計、錯誤處理、條件編譯等有更深的瞭解。現在只要牢牢記住其中的兩行程式碼:

xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");

xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");

這兩行程式碼基本上就是嘗試使用一個版本的 MSXML 建立物件,如果失敗則使用另一個版本建立該物件。不錯吧?如果都不成功,則將 xmlHttp 變數設為 false,告訴您的程式碼出現了問題。如果出現這種情況,可能是因為安裝了非 Microsoft 瀏覽器,需要使用不同的程式碼。

處理 Mozilla 和非 Microsoft 瀏覽器

如果選擇的瀏覽器不是 Internet Explorer,或者為非 Microsoft 瀏覽器設計程式碼,就需要使用不同的程式碼。事實上就是 清單 1 所示的一行簡單程式碼:

var xmlHttp = new XMLHttpRequest object;

這行簡單得多的程式碼在 Mozilla、Firefox、Safari、Opera 以及基本上所有以任何形式或方式支援 Ajax 的非 Microsoft 瀏覽器中,建立了 XMLHttpRequest 對象。

結合起來

關鍵是要支援所有 瀏覽器。誰願意設計一個只能用於 Internet Explorer 或者非 Microsoft 瀏覽器的應用程式呢?或者更糟,要設計一個應用程式兩次?當然不!因此程式碼要同時支援 Internet Explorer 和非 Microsoft 瀏覽器。清單 4 顯示了這樣的程式碼。


清單 4. 以支援多種瀏覽器的方式建立 XMLHttpRequest 物件


/* Create a new XMLHttpRequest object to talk to the Web server */
var xmlHttp = false;
/*@cc_on @*/
/*@if (@_jscript_version >= 5)
try {
  xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
  try {
    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (e2) {
    xmlHttp = false;
  }
}
@end @*/

if (!xmlHttp && typeof XMLHttpRequest != 'undefined') {
  xmlHttp = new XMLHttpRequest();
}

現在先不管那些注釋的奇怪符號,如 @cc_on,這是特殊的 JavaScript 編譯器命令,將在下一期針對 XMLHttpRequest 的文章中詳細討論。這段程式碼的核心分為三步:

  1. 建立一個變數 xmlHttp 來引用即將建立的 XMLHttpRequest 對象。
  2. 嘗試在 Microsoft 瀏覽器中建立該對象:
    • 嘗試使用 Msxml2.XMLHTTP 對象建立它。
    • 如果失敗,再嘗試 Microsoft.XMLHTTP 對象。
  3. 如果仍然沒有建立 xmlHttp,則以非 Microsoft 的方式建立該物件。

最後,xmlHttp 應該引用一個有效的 XMLHttpRequest 物件,無論運行什麼樣的瀏覽器。

關於安全性的一點說明

安全性如何呢?現在瀏覽器允許用戶提高他們的安全等級,關閉 JavaScript 技術,禁用瀏覽器中的任何選項。在這種情況下,程式碼無論如何都不會工作。此時必須適當地處理問題,這需要單獨的一篇文章來討論,要放到未來了(這個系列夠長了吧?不用擔心,讀完之前也許您就掌握了)。現在要設計一段強健但不夠完美的程式碼,對於掌握 Ajax 來說就很好了。以後我們還將討論更多的細節。



回到頂端


Ajax 世界中的請求/回應

現在我們介紹了 Ajax,對 XMLHttpRequest 物件以及如何建立它也有了基本的瞭解。如果閱讀得很仔細,您可能已經知道與伺服器上的 Web 應用程式打交道的是 JavaScript 技術,而不是直接提交給那個應用程式的 HTML 表單。

還缺少什麼呢?到底如何使用 XMLHttpRequest。因為這段程式碼非常重要,您設計的每個 Ajax 應用程式都要以某種形式使用它,先看看 Ajax 的基本請求/回應模型是什麼樣吧。

發出請求

您已經有了一個嶄新的 XMLHttpRequest 物件,現在讓它幹點活兒吧。首先需要一個 Web 頁面能夠引用的 JavaScript 方法(比如當使用者輸入文字或者從功能表中選擇一項時)。接下來就是在所有 Ajax 應用程式中基本都雷同的流程:

  1. 從 Web 表單中獲取需要的資料。
  2. 建立要連接的 URL。
  3. 打開到伺服器的連接。
  4. 設置伺服器在完成後要執行的函數。
  5. 發送請求。

清單 5 中的範例 Ajax 方法就是按照這個順序組織的:


清單 5. 發出 Ajax 請求


function callServer() {
  // Get the city and state from the web form
  var city = document.getElementById("city").value;
  var state = document.getElementById("state").value;
  // Only go on if there are values for both fields
  if ((city == null) || (city == "")) return;
  if ((state == null) || (state == "")) return;

  // Build the URL to connect to
  var url = "/scripts/getZipCode.php?city=" + escape(city) + "&state=" + escape(state);

  // Open a connection to the server
  xmlHttp.open("GET", url, true);

  // Setup a function for the server to run when it's done
  xmlHttp.onreadystatechange = updatePage;

  // Send the request
  xmlHttp.send(null);
}

其中大部分程式碼意義都很明確。開始的程式碼使用基本 JavaScript 程式碼獲取幾個表單字段的值。然後設置一個 PHP 腳本作為連結的目標。要注意腳本 URL 的指定方式,city 和 state(來自表單)使用簡單的 GET 參數附加在 URL 之後。

然後打開一個連接,這是您第一次看到使用 XMLHttpRequest。其中指定了連接方法(GET)和要連接的 URL。最後一個參數如果設為 true,那麼將請求一個非同步連接(這就是 Ajax 的由來)。如果使用 false,那麼程式碼發出請求後將等待伺服器返回的回應。如果設為 true,當伺服器在後臺處理請求的時候用戶仍然可以使用表單(甚至引用其他 JavaScript 方法)。

xmlHttp(要記住,這是 XMLHttpRequest 物件實例)的 onreadystatechange 屬性可以告訴伺服器在執行完成 後(可能要用五分鐘或者五個小時)做什麼。因為程式碼沒有等待伺服器,必須讓伺服器知道怎麼做以便您能作出回應。在這個範例中,如果伺服器處理完了請求,一個特殊的名為 updatePage() 的方法將被觸發。

最後,使用值 null 引用 send()。因為已經在請求 URL 中增加了要發送給伺服器的資料(city 和 state),所以請求中不需要傳送任何資料。這樣就發出了請求,伺服器按照您的要求工作。

如果沒有發現任何新鮮的東西,您應該體會到這是多麼簡單明瞭!除了牢牢記住 Ajax 的非同步特性外,這些內容都相當簡單。應該感激 Ajax 使您能夠專心設計漂亮的應用程式和介面,而不用擔心複雜的 HTTP 請求/回應程式碼。

清單 5 中的程式碼說明了 Ajax 的易用性。資料是簡單的文字,可以作為請求 URL 的一部分。用 GET 而不是更複雜的 POST 發送請求。沒有 XML 和要增加的內容頭部,請求中沒有要傳送的資料;換句話說,這就是 Ajax 的烏托邦。

不用擔心,隨著本系列文章的展開,事情會變得越來越複雜。您將看到如何發送 POST 請求、如何設置請求頭部和內容類型、如何在訊息中設計 XML、如何增加請求的安全性,可以做的工作還有很多!暫時先不用管那些困難點,掌握好基本的東西就行了,很快我們就會建立一整套的 Ajax 工具庫。

處理回應

現在要面對伺服器的回應了。現在只要知道兩點:

  • 什麼也不要做,直到 xmlHttp.readyState 屬性的值等於 4。
  • 伺服器將把回應填寫到 xmlHttp.responseText 屬性中。

其中的第一點,即就緒狀態,將在下一篇文章中詳細討論,您將進一步瞭解 HTTP 請求的階段,可能比您設想的還多。現在只要檢查一個特定的值(4)就可以了(下一期文章中還有更多的值要介紹)。第二點,使用 xmlHttp.responseText 屬性獲得伺服器的回應,這很簡單。清單 6 中的範例方法可供伺服器根據 清單 5 中發送的資料引用。


清單 6. 處理伺服器回應


function updatePage() {
  if (xmlHttp.readyState == 4) {
    var response = xmlHttp.responseText;
    document.getElementById("zipCode").value = response;
  }
}

這些程式碼同樣既不難也不複雜。它等待伺服器調用,如果是就緒狀態,則使用伺服器返回的值(這裏是使用者輸入的城市和州的 ZIP 代碼)設置另一個表單字段的值。於是包含 ZIP 代碼的 zipCode 欄位突然出現了,而使用者沒有按任何按鈕!這就是前面所說的視窗應用程式的感覺。快速回應、動態感受等等,這些都只因為有了小小的一段 Ajax 程式碼。

細心的讀者可能注意到 zipCode 是一個普通的文字欄位。一旦伺服器傳回 ZIP 代碼,updatePage() 方法就用城市/州的 ZIP 代碼設置那個欄位的值,用戶就可以改寫該值。這樣做有兩個原因:保持例子簡單,說明有時候可能希望 用戶能夠修改伺服器返回的資料。要記住這兩點,它們對於好的用戶介面設計來說很重要。



回到頂端


連接 Web 表單

還有什麼呢?實際上沒有多少了。一個 JavaScript 方法獲取用戶輸入表單的資訊並將其發送到伺服器,另一個 JavaScript 方法監聽和處理回應,並在回應傳回時設置欄位的值。所有這些實際上都依賴於引用 第一個 JavaScript 方法,它啟動了整個過程。最明顯的辦法是在 HTML 表單中增加一個按鈕,但這是 2001 年的辦法,您不這樣認為嗎?還是像 清單 7 這樣利用 JavaScript 技術吧。


清單 7. 啟動一個 Ajax 過程


<form>
 <p>City: <input type="text" name="city" id="city" size="25" 
       onChange="callServer();" /></p>
 <p>State: <input type="text" name="state" id="state" size="25" 
       onChange="callServer();" /></p>
 <p>Zip Code: <input type="text" name="zipCode" id="city" size="5" /></p>
</form>

如果感覺這像是一段相當普通的程式碼,那就對了,正是如此!當用戶在 city 或 state 欄位中輸入新的值時,callServer() 方法就被觸發,於是 Ajax 開始執行了。有點明白怎麼回事了吧?好,就是如此!



回到頂端


結束語

現在您可能已經準備開始設計第一個 Ajax 應用程式了,至少也希望認真讀一下 參考資料 中的那些文章了吧?但可以首先從這些應用程式如何工作的基本概念開始,對 XMLHttpRequest 物件有基本的瞭解。在下一期文章中,您將掌握這個物件,學會如何處理 JavaScript 和伺服器的通訊、如何使用 HTML 表單以及如何獲得 DOM 控制碼。

現在先花點時間考慮考慮 Ajax 應用程式有多麼強大。設想一下,當點選按鈕、輸入一個欄位、從下拉式選單中選擇一個功能或者用滑鼠在螢幕上拖動時,Web 表單能夠立刻作出回應會是什麼情形。想一想非同步 究竟意味著什麼,想一想 JavaScript 程式碼執行而且不等待 伺服器對它的請求作出回應。會遇到什麼樣的問題?會進入什麼樣的領域?考慮到這種新的方法,程式設計的時候應如何改變表單的設計?

如果在這些問題上花一點時間,與簡單地剪下/貼上某些程式碼到您根本不理解的應用程式中相比,收益會更多。在下一期文章中,我們將把這些概念付諸實踐,詳細介紹使應用程式按照這種方式工作所需要的程式碼。因此,現在先享受一下 Ajax 所帶來的可能性吧。



回到頂端


參考資料

學習

討論


回到頂端


關於作者

Brett McLaughlin 的照片

Brett McLaughlin 從 Logo 時代就開始使用電腦。(還記得那個小三角嗎?)近年來,他已經成為 Java 和 XML 社群最著名的作者和程式設計師之一。他曾經在 Nextel Communications 施行過複雜的企業系統,在 Lutris Technologies 編寫過應用伺服器,最近在 O'Reilly Media, Inc. 繼續撰寫和編輯這方面的圖書。Brett 即將出版的新書 Head Rush Ajax,和暢銷書作者 Eric 與 Beth Freeman 一起為 Ajax 帶來了獲獎的革命性 Head First 方法。最近的著作 Java 1.5 Tiger: A Developer's Notebook 是關於 Java 技術最新版本的第一本書,經典的 Java and XML 仍然是在 Java 語言中使用 XML 技術的權威著作。




回到頂端


對本文的評價

不甚滿意!(1)
可再加強 (2)
持平 (3)
相當不錯 (4)
受益匪淺!(5)



回到頂端


Other company, product, or service names may be trademarks or service marks of others.


    關於IBM隱私權條款聯絡我們