Ajax入門

Ajax 由 HTML、JavaScript™ 技術、DHTML 和 DOM 組成,這一傑出的方法能夠將笨拙的 Web 界面轉化成交互性的 Ajax 應用程序。 本系列的做者是一位 Ajax 專家,他演示了這些技術如何協同工做 —— 從整體概述到細節的討論 —— 使高效的 Web 開發成爲現實。他還揭開了 Ajax 核心概念的神祕面紗,包括 XMLHttpRequest 對象。
Ajax 不 僅僅 是一種時尚,它是一種構建網站的強大方法,並且不像學習一種全新的語言那樣困難。
請訪問 Ajax 技術資源中心,這是有關 Ajax 編程模型信息的一站式中心,包括不少文檔、教程、論壇、blog、wiki 和新聞。任何新信息都能在這裏找到。
但在詳細探討 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。這是一個 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 的強大之處。它能夠根據須要自行與服務器進行交互,用戶甚至能夠徹底不知道幕後發生的一切。結果就是相似於桌面應用程序的動態、快速響應、高交互性的體驗,可是背後又擁有互聯網的所有強大力量。
獲得 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 有點兒使人生畏,HTML 設計者不多使用它,即便 JavaScript 程序員也不大用到它,除非要完成某項高端編程任務。大量使用 DOM 的 複雜的 Java 和 C/C++ 程序,這可能就是 DOM 被認爲難以學習的緣由。
幸運的是,在 JavaScript 技術中使用 DOM 很容易,也很是直觀。如今,按照常規也許應該說明如何使用 DOM,或者至少要給出一些示例代碼,但這樣作也可能誤導您。即便不理會 DOM,仍然能深刻地探討 Ajax,這也是我準備採用的方法。之後的文章將再次討論 DOM,如今只要知道可能須要 DOM 就能夠了。當須要在 JavaScript 代碼和服務器之間傳遞 XML 和改變 HTML 表單的時候,咱們再深刻研究 DOM。沒有它也能作一些有趣的工做,所以如今就把 DOM 放到一邊吧。




回頁首


有了上面的基礎知識後,咱們來看看一些具體的例子。 XMLHttpRequest 是 Ajax 應用程序的核心,並且對不少讀者來講可能還比較陌生,咱們就從這裏開始吧。從 清單 1 能夠看出,建立和使用這個對象很是簡單,不是嗎?等一等。
還記得幾年前的那些討厭的瀏覽器戰爭嗎?沒有同樣東西在不一樣的瀏覽器上獲得一樣的結果。無論您是否相信,這些戰爭仍然在繼續,雖然規模較小。但使人奇怪的是, XMLHttpRequest 成了這場戰爭的犧牲品之一。所以得到 XMLHttpRequest 對象可能須要採用不一樣的方法。下面我將詳細地進行解釋。
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 瀏覽器,須要使用不一樣的代碼。
若是選擇的瀏覽器不是 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,對 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 編碼設置那個字段的值,用戶就能夠改寫該值。這樣作有兩個緣由:保持例子簡單,說明有時候可能 但願 用戶可以修改服務器返回的數據。要記住這兩點,它們對於好的用戶界面設計來講很重要。




回頁首


還有什麼呢?實際上沒有多少了。一個 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
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 技術的權威著做。
相關文章
相關標籤/搜索