Ajax程序設計入門

  一、使用Ajax的主要原因

  1、通過適當的Ajax應用達到更好的用戶體驗;

  2、把以前的一些服務器負擔的工作轉嫁到客戶端,利于客戶端閑置的處理能力來處理,減輕服務器和帶寬的負擔,從而達到節約ISP的空間及帶寬租用成本的目的。

  二、引用

  Ajax這個概念的最早提出者Jesse James Garrett認為:Ajax是Asynchronous JavaScript and XML的縮寫。Ajax并不是一門新的語言或技術,它實際上是幾項技術按一定的方式組合在一在同共的協作中發揮各自的作用,它包括:

  ·使用XHTML和CSS標準化呈現;
  ·使用DOM實現動態顯示和交互;
  ·使用XML和XSLT進行數據交換與處理;
  ·使用XMLHttpRequest進行異步數據讀取;
  ·最后用JavaScript綁定和處理所有數據;

  Ajax的工作原理相當于在用戶和服務器之間加了—個中間層,使用戶操作與服務器響應異步化。并不是所有的用戶請求都提交給服務器,像—些數據驗證和數據處理等都交給Ajax引擎自己來做,只有確定需要從服務器讀取新數據時再由Ajax引擎代為向服務器提交請求。

  圖2-1

  圖2-2

  三、概述

  雖然Garrent列出了7條Ajax的構成技術,但個人認為,所謂的Ajax其核心只有JavaScript、XMLHTTPRequest和DOM,如果所用數據格式為XML的話,還可以再加上XML這一項(Ajax從服務器端返回的數據可以是XML格式,也可以是文本等其他格式)。

  在舊的交互方式中,由用戶觸發一個HTTP請求到服務器,服務器對其進行處理后再返回一個新的HTHL頁到客戶端,每當服務器處理客戶端提交的請求時,客戶都只能空閑等待,并且哪怕只是一次很小的交互、只需從服務器端得到很簡單的一個數據,都要返回一個完整的HTML頁,而用戶每次都要浪費時間和帶寬去重新讀取整個頁面。

  而使用Ajax后用戶從感覺上幾乎所有的操作都會很快響應沒有頁面重載(白屏)的等待。

  1、XMLHTTPRequest

  Ajax的一個最大的特點是無需刷新頁面便可向服務器傳輸或讀寫數據(又稱無刷新更新頁面),這一特點主要得益于XMLHTTP組件XMLHTTPRequest對象。這樣就可以向再發桌面應用程序只同服務器進行數據層面的交換,而不用每次都刷新界面也不用每次將數據處理的工作提交給服務器來做,這樣即減輕了服務器的負擔又加快了響應速度、縮短了用戶等候時間。

  最早應用XMLHTTP的是微軟,IE(IE5以上)通過允許開發人員在Web頁面內部使用XMLHTTP ActiveX組件擴展自身的功能,開發人員可以不用從當前的Web頁面導航而直接傳輸數據到服務器上或者從服務器取數據。這個功能是很重要的,因為它幫助減少了無狀態連接的痛苦,它還可以排除下載冗余HTML的需要,從而提高進程的速度。Mozilla(Mozilla1.0以上及NetScape7以上)做出的回應是創建它自己的繼承XML代理類:XMLHttpRequest類。Konqueror (和Safari v1.2,同樣也是基于KHTML的瀏覽器)也支持XMLHttpRequest對象,而Opera也將在其v7.6x+以后的版本中支持XMLHttpRequest對象。對于大多數情況,XMLHttpRequest對象和XMLHTTP組件很相似,方法和屬性也類似,只是有一小部分屬性不支持。

  XMLHttpRequest的應用:

  ·XMLHttpRequest對象在JS中的應用

var xmlhttp = new XMLHttpRequest();

  ·微軟的XMLHTTP組件在JS中的應用

var xmlhttp = new ActiveXObject(Microsoft.XMLHTTP);
var xmlhttp = new ActiveXObject(Msxml2.XMLHTTP);
XMLHttpRequest 對象方法
/**
* Cross-browser XMLHttpRequest instantiation.
*/

if (typeof XMLHttpRequest == ’undefined’) {
 XMLHttpRequest = function () {
  var msxmls = [’MSXML3’, ’MSXML2’, ’Microsoft’]
  for (var i=0; i < msxmls.length; i++) {
   try {
    return new ActiveXObject(msxmls[i]+’.XMLHTTP’)
   } catch (e) { }
  }
  throw new Error("No XML component installed!")
 }
}
function createXMLHttpRequest() {
 try {
  // Attempt to create it "the Mozilla way"
  if (window.XMLHttpRequest) {
   return new XMLHttpRequest();
  }
  // Guess not - now the IE way
  if (window.ActiveXObject) {
   return new ActiveXObject(getXMLPrefix() + ".XmlHttp");
  }
 }
 catch (ex) {}
 return false;
};

  XMLHttpRequest 對象方法

?方法?描述
?abort()?停止當前請求
?getAllResponseHeaders()?作為字符串返問完整的headers
?getResponseHeader("headerLabel")?作為字符串返問單個的header標簽
?open("method","URL"[,asyncFlag[,"userName"[, "password"]]])?設置未決的請求的目標 URL, 方法, 和其他參數
?send(content)?發送請求
?setRequestHeader("label", "value")?設置header并和請求一起發送

  XMLHttpRequest 對象屬性

?屬性?描述
?onreadystatechange?狀態改變的事件觸發器
?readyState?對象狀態(integer):
?0 = 未初始化
?1 = 讀取中
?2 = 已讀取
?3 = 交互中
?4 = 完成
?responseText?服務器進程返回數據的文本版本
?responseXML?服務器進程返回數據的兼容DOM的XML文檔對象
?status?服務器返回的狀態碼, 如:404 = "文件末找到" 、200 ="成功"
?statusText?服務器返回的狀態文本信息

  2、JavaScript

  JavaScript是一在瀏覽器中大量使用的編程語言,,他以前一直被貶低為一門糟糕的語言(他確實在使用上比較枯燥),以在常被用來作一些用來炫耀的小玩意和惡作劇或是單調瑣碎的表單驗證。但事實是,他是一門真正的編程語言,有著自已的標準并在各種瀏覽器中被廣泛支持。

  3、DOM

  Document Object Model。

  DOM是給 HTML 和 XML 文件使用的一組 API。它提供了文件的結構表述,讓你可以改變其中的內容及可見物。其本質是建立網頁與 Script 或程序語言溝通的橋梁。

  所有WEB開發人員可操作及建立文件的屬性、方法及事件都以對象來展現(例如,document 就代表“文件本身“這個對像,table 對象則代表 HTML 的表格對象等等)。這些對象可以由當今大多數的瀏覽器以 Script 來取用。

  一個用HTML或XHTML構建的網頁也可以看作是一組結構化的數據,這些數據被封在DOM(Document Object Model)中,DOM提供了網頁中各個對象的讀寫的支持。

  4、XML

  可擴展的標記語言(Extensible Markup Language)具有一種開放的、可擴展的、可自描述的語言結構,它已經成為網上數據和文檔傳輸的標準。它是用來描述數據結構的一種語言,就正如他的名字一樣。他使對某些結構化數據的定義更加容易,并且可以通過他和其他應用程序交換數據。

  5、綜合

  Jesse James Garrett提到的Ajax引擎,實際上是一個比較復雜的JavaScript應用程序,用來處理用戶請求,讀寫服務器和更改DOM內容。

  JavaScript的Ajax引擎讀取信息,并且互動地重寫DOM,這使網頁能無縫化重構,也就是在頁面已經下載完畢后改變頁面內容,這是我們一直在通過JavaScript和DOM在廣泛使用的方法,但要使網頁真正動態起來,不僅要內部的互動,還需要從外部獲取數據,在以前,我們是讓用戶來輸入數據并通過DOM來改變網頁內容的,但現在,XMLHTTPRequest,可以讓我們在不重載頁面的情況下讀寫服務器上的數據,使用戶的輸入達到最少。

  基于XML的網絡通訊也并不是新事物,實際上FLASH和JAVA Applet都有不錯的表現,現在這種富交互在網頁上也可用了,基于標準化的并被廣泛支持和技術,并且不需要插件或下載小程序。

  Ajax是傳統WEB應用程序的一個轉變。以前是服務器每次生成HTML頁面并返回給客戶端(瀏覽器)。在大多數網站中,很多頁面中至少90%都是一樣的,比如:結構、格式、頁頭、頁尾、廣告等,所不同的只是一小部分的內容,但每次服務器都會生成所有的頁面再返回給客戶端,這無形之中是一種浪費,不管是對于用戶的時間、帶寬、CPU耗用,還是對于ISP的高價租用的帶寬和空間來說。如果按一頁來算,只能幾K或是幾十K可能并不起眼,但像SINA每天要生成幾百萬個頁面的大ISP來說,可以說是損失巨大的。而AJAX可以所為客戶端和服務器的中間層,來處理客戶端的請求,并根據需要向服務器端發送請求,用什么就取什么、用多少就取多少,就不會有數據的冗余和浪費,減少了數據下載總量,而且更新頁面時不用重載全部內容,只更新需要更新的那部分即可,相對于純后臺處理并重載的方式縮短了用戶等待時間,也把對資源的浪費降到最低,基于標準化的并被廣泛支持和技術,并且不需要插件或下載小程序,所以Ajax對于用戶和ISP來說是雙盈的。

  Ajax使WEB中的界面與應用分離(也可以說是數據與呈現分離),而在以前兩者是沒有清晰的界限的,數據與呈現分離的分離,有利于分工合作、減少非技術人員對頁面的修改造成的WEB應用程序錯誤、提高效率、也更加適用于現在的發布系統。也可以把以前的一些服務器負擔的工作轉嫁到客戶端,利于客戶端閑置的處理能力來處理。

  四、應用

  Ajax理念的出現,揭開了無刷新更新頁面時代的序幕,并有代替傳統web開發中采用form(表單)遞交方式更新web頁面的趨勢,可以算是一個里程碑。但Ajax都不是適用于所有地方的,它的適用范圍是由它的特性所決定的。

  舉個應用的例子,是關于級聯菜單方面的Ajax應用。

  我們以前的對級聯菜單的處理是這樣的:

  為了避免每次對菜單的操作引起的重載頁面,不采用每次調用后臺的方式,而是一次性將級聯菜單的所有數據全部讀取出來并寫入數組,然后根據用戶的操作用JavaScript來控制它的子集項目的呈現,這樣雖然解決了操作響應速度、不重載頁面以及避免向服務器頻繁發送請求的問題,但是如果用戶不對菜單進行操作或只對菜單中的一部分進行操作的話,那讀取的數據中的一部分就會成為冗余數據而浪費用戶的資源,特別是在菜單結構復雜、數據量大的情況下(比如菜單有很多級、每一級菜又有上百個項目),這種弊端就更為突出。

  如果在此案中應用Ajax后,結果就會有所改觀:

  在初始化頁面時我們只讀出它的第一級的所有數據并顯示,在用戶操作一級菜單其中一項時,會通過Ajax向后臺請求當前一級項目所屬的二級子菜單的所有數據,如果再繼續請求已經呈現的二級菜單中的一項時,再向后面請求所操作二級菜單項對應的所有三級菜單的所有數據,以此類推……這樣,用什么就取什么、用多少就取多少,就不會有數據的冗余和浪費,減少了數據下載總量,而且更新頁面時不用重載全部內容,只更新需要更新的那部分即可,相對于后臺處理并重載的方式縮短了用戶等待時間,也把對資源的浪費降到最低。

  此外,Ajax由于可以調用外部數據,也可以實現數據聚合的功能(當然要有相應授權),比如微軟剛剛在3月15日發布的在線RSS閱讀器BETA版;還可以利于一些開放的數據,開發自已的一些應用程序,比如用Amazon的數據作的一些新穎的圖書搜索應用。

  總之,Ajax適用于交互較多,頻繁讀數據,數據分類良好的WEB應用。

  五、Ajax的優勢

  1、減輕服務器的負擔。因為Ajax的根本理念是“按需取數據”,所以最大可能在減少了冗余請求和響影對服務器造成的負擔;

  2、無刷新更新頁面,減少用戶實際和心理等待時間;

  首先,“按需取數據”的模式減少了數據的實際讀取量,打個很形象的比方,如果說重載的方式是從一個終點回到原點再到另一個終點的話,那么Ajax就是以一個終點為基點到達另一個終點;

  圖5-1

  圖5-2

  其次,即使要讀取比較大的數據,也不用像RELOAD一樣出現白屏的情況,由于Ajax是用XMLHTTP發送請求得到服務端應答數據,在不重新載入整個頁面的情況下用Javascript操作DOM最終更新頁面的,所以在讀取數據的過程中,用戶所面對的也不是白屏,而是原來的頁面狀態(或者可以加一個LOADING的提示框讓用戶了解數據讀取的狀態),只有當接收到全部數據后才更新相應部分的內容,而這種更新也是瞬間的,用戶幾乎感覺不到。總之用戶是很敏感的,他們能感覺到你對他們的體貼,雖然不太可能立竿見影的效果,但會在用戶的心中一點一滴的積累他們對網站的依賴。

  3、更好的用戶體驗;

  4、也可以把以前的一些服務器負擔的工作轉嫁到客戶端,利于客戶端閑置的處理能力來處理,減輕服務器和帶寬的負擔,節約空間和帶寬租用成本;

  5、Ajax由于可以調用外部數據;

  6、基于標準化的并被廣泛支持和技術,并且不需要插件或下載小程序;

  7、Ajax使WEB中的界面與應用分離(也可以說是數據與呈現分離);

  8、對于用戶和ISP來說是雙盈的。

  六、Ajax的問題

  1、一些手持設備(如手機、PDA等)現在還不能很好的支持Ajax;

  2、用JavaScript作的Ajax引擎,JavaScript的兼容性和DeBug都是讓人頭痛的事;

  3、Ajax的無刷新重載,由于頁面的變化沒有刷新重載那么明顯,所以容易給用戶帶來困擾――用戶不太清楚現在的數據是新的還是已經更新過的;現有的解決有:在相關位置提示、數據更新的區域設計得比較明顯、數據更新后給用戶提示等;

  4、對流媒體的支持沒有FLASH、Java Applet好;

  七、結束語

  更好的Ajax應用,需要更多的客戶端的開發,和對當前的WEB應用理念的思考,而且良好的用戶體驗,來源于為處處用戶考慮的理念,而不單純是某種技術。

——————————————————————————————————————————
AJAX開發簡略

在使用瀏覽器瀏覽網頁的時候,當頁面刷新很慢的時候,你的瀏覽器在干什么?你的屏幕內容是什么?是的,你的瀏覽器在等待刷新,而你的屏幕內容是一片空白,而你在屏幕前苦苦的等待瀏覽器的響應。開發人員為了克服這種尷尬的局面,不得不在每一個可能需要長時間等待響應的頁面上增加一個DIV,告訴用戶“系統正在處理您的請求,請稍候……”。

現在,有一種越來越流行越熱的“老”技術,可以徹底改變這種窘迫的局面。那就是AJAX。如今,隨著Gmail、Google-maps的應用和各種瀏覽器的支持,AJAX正逐漸吸引全世界的眼球。

一、AJAX定義
AJAX(Asynchronous JavaScript and XML)其實是多種技術的綜合,包括Javascript、XHTML和CSS、DOM、XML和XSTL、XMLHttpRequest。其中:

使用XHTML和CSS標準化呈現,使用DOM實現動態顯示和交互,使用XML和XSTL進行數據交換與處理,使用XMLHttpRequest對象進行異步數據讀取,使用Javascript綁定和處理所有數據。

在AJAX提出之前,業界對于上述技術都只是單獨的使用,沒有綜合使用,也是由于之前的技術需求所決定的。隨著應用的廣泛,AJAX也成為香餑餑了。

二、現狀與需要解決的問題
傳統的Web應用采用同步交互過程,這種情況下,用戶首先向HTTP服務器觸發一個行為或請求的呼求。反過來,服務器執行某些任務,再向發出請求的用戶返回一個HTML頁面。這是一種不連貫的用戶體驗,服務器在處理請求的時候,用戶多數時間處于等待的狀態,屏幕內容也是一片空白。如下圖:


web1.jpg
web2.jpg

自從采用超文本作為Web傳輸和呈現之后,我們都是采用這么一套傳輸方式。當負載比較小的時候,這并不會體現出有什么不妥。可是當負載比較大,響應時間要很長,1分鐘、2分鐘……數分鐘的時候,這種等待就不可忍受了。嚴重的,超過響應時間,服務器干脆告訴你頁面不可用。另外,某些時候,我只是想改變頁面一小部分的數據,那為什么我必須重新加載整個頁面呢?!當軟件設計越來越講究人性化的時候,這么糟糕的用戶體驗簡直與這種原則背道而馳。為什么老是要讓用戶等待服務器取數據呢?至少,我們應該減少用戶等待的時間。現在,除了程序設計、編碼優化和服務器調優之外,還可以采用AJAX。

三、為什么使用AJAX
與傳統的Web應用不同,AJAX采用異步交互過程。AJAX在用戶與服務器之間引入一個中間媒介,從而消除了網絡交互過程中的處理—等待—處理—等待缺點。用戶的瀏覽器在執行任務時即裝載了AJAX引擎。AJAX引擎用JavaScript語言編寫,通常藏在一個隱藏的框架中。它負責編譯用戶界面及與服務器之間的交互。AJAX引擎允許用戶與應用軟件之間的交互過程異步進行,獨立于用戶與網絡服務器間的交流。現在,可以用Javascript調用AJAX引擎來代替產生一個HTTP的用戶動作,內存中的數據編輯、頁面導航、數據校驗這些不需要重新載入整個頁面的需求可以交給AJAX來執行。

AJAX web響應過程1.jpg
AJAX web響應過程2.jpg

使用AJAX,可以為ISP、開發人員、終端用戶帶來可見的便捷:

l 減輕服務器的負擔。AJAX的原則是“按需取數據”,可以最大程度的減少冗余請求,和響應對服務器造成的負擔。

l 無刷新更新頁面,減少用戶心理和實際的等待時間。特別的,當要讀取大量的數據的時候,不用像Reload那樣出現白屏的情況,AJAX使用XMLHTTP對象發送請求并得到服務器響應,在不重新載入整個頁面的情況下用Javascript操作DOM最終更新頁面。所以在讀取數據的過程中,用戶所面對的不是白屏,是原來的頁面內容(也可以加一個Loading的提示框讓用戶知道處于讀取數據過程),只有當數據接收完畢之后才更新相應部分的內容。這種更新是瞬間的,用戶幾乎感覺不到。

l 帶來更好的用戶體驗。

l 可以把以前一些服務器負擔的工作轉嫁到客戶端,利用客戶端閑置的能力來處理,減輕服務器和帶寬的負擔,節約空間和寬帶租用成本。

l 可以調用外部數據。

l 基于標準化的并被廣泛支持的技術,不需要下載插件或者小程序。

l 進一步促進頁面呈現和數據的分離。

四、誰在使用AJAX
在應用AJAX開發上面,Google當仁不讓是表率。Orkut、Gmail、Google Groups、Google Maps、Google Suggest都應用了這項技術。Amazon的A9.com搜索引擎也采用了類似的技術。

微軟也在積極開發更為完善的AJAX應用:它即將推出代號為Atlas的AJAX工具。Atlas的功能超越了AJAX本身,包括整合Visual Studio的調試功能。另外,新的ASP.NET控件將使客戶端控件與服務器端代碼的捆綁更為簡便。Atlas客戶腳本框架(Atlas Clent Script Framework)也使與網頁及相關項目的交互更為便利。但Visual Studio 2005中并不包含此項功能。

微軟最近宣布Atlas客戶腳本框架將包含如下內容(詳細資料請訪問Atlas計劃網站):

* 一個可擴展的核心框架,它添加了JavaScript功能:如生命同時期管理、繼承管理、多點傳送處理器和界面管理。

* 一個常見功能的基本類庫,有豐富的字符串處理、計時器和運行任務。

* 為HTML附加動態行為的用戶界面框架。

* 一組用來簡化服務器連通和網絡訪問的網絡堆棧。

* 一組豐富的用戶界面開發控件,如:自動完成的文本框、動畫和拖放。

* 處理瀏覽器腳本行為差異的瀏覽器兼容層面。

典型的,微軟將AJAX技術應用在MSN Space上面。很多人一直都對MS Space服務感到很奇怪,當提交回復評論以后,瀏覽器會暫時停頓一下,然后在無刷新的情況下把我提交的評論顯示出來。這個就是應用了AJAX的效果。試想,如果添加一個評論就要重新刷新整個頁面,那可真費事。

目前,AJAX應用最普遍的領域是GIS-Map方面。GIS的區域搜索強調快速響應,AJAX的特點正好符合這種需求。

五、用AJAX改進你的設計
AJAX雖然可以實現無刷新更新頁面內容,但是也不是什么地方都可以用,主要應用在交互較多、頻繁讀數據、數據分類良好的Web應用中。現在,讓我們舉兩個例子,看看如何用AJAX改進你的設計。

例子1:數據校驗在輸入form表單內容的時候,我們通常需要確保數據的唯一性。因此,常常在頁面上提供“唯一性校驗”按鈕,讓用戶點擊,打開一個校驗小窗口;或者等form提交到服務器端,由服務器判斷后在返回相應的校驗信息。前者,window.open操作本來就是比較耗費資源的,通常由window. showModalDialog代替,即使這樣也要彈出一個對話框;后者,需要把整個頁面提交到服務器并由服務器判斷校驗,這個過程不僅時間長而且加重了服務器負擔。而使用AJAX,這個校驗請求可以由XMLHttpRequest對象發出,整個過程不需要彈出新窗口,也不需要將整個頁面提交到服務器,快速又不加重服務器負擔。

例子2:按需取數據—級聯菜單以前,為了避免每次對菜單的操作引起的重載頁面,不采用每次調用后臺的方式,而是一次性將級聯菜單的所有數據全部讀取出來并寫入數組,然后根據用戶的操作用JavaScript來控制它的子集項目的呈現,這樣雖然解決了操作響應速度、不重載頁面以及避免向服務器頻繁發送請求的問題,但是如果用戶不對菜單進行操作或只對菜單中的一部分進行操作的話,那讀取的數據中的一部分就會成為冗余數據而浪費用戶的資源,特別是在菜單結構復雜、數據量大的情況下(比如菜單有很多級、每一級菜又有上百個項目),這種弊端就更為突出。

現在應用AJAX,在初始化頁面時我們只讀出它的第一級的所有數據并顯示,在用戶操作一級菜單其中一項時,會通過Ajax向后臺請求當前一級項目所屬的二級子菜單的所有數據,如果再繼續請求已經呈現的二級菜單中的一項時,再向后面請求所操作二級菜單項對應的所有三級菜單的所有數據,以此類推……這樣,用什么就取什么、用多少就取多少,就不會有數據的冗余和浪費,減少了數據下載總量,而且更新頁面時不用重載全部內容,只更新需要更新的那部分即可,相對于后臺處理并重載的方式縮短了用戶等待時間,也把對資源的浪費降到最低。

例子3:讀取外部數據AJAX可以調用外部數據,因此,可以對一些開發的數據比如XML文檔、RSS文檔進行二次加工,實現數據整合或者開發應用程序。

六、AJAX的缺陷
AJAX不是完美的技術。使用AJAX,它的一些缺陷不得不權衡一下:

l AJAX大量使用了Javascript和AJAX引擎,而這個取決于瀏覽器的支持。IE5.0及以上、Mozilla1.0、NetScape7及以上版本才支持,Mozilla雖然也支持AJAX,但是提供XMLHttpRequest的方式不一樣。所以,使用AJAX的程序必須測試針對各個瀏覽器的兼容性。

l AJAX更新頁面內容的時候并沒有刷新整個頁面,因此,網頁的后退功能是失效的;有的用戶還經常搞不清楚現在的數據是舊的還是已經更新過的。這個就需要在明顯位置提醒用戶“數據已更新”。

l 對流媒體的支持沒有FLASH、Java Applet好。

l 一些手持設備(如手機、PDA等)現在還不能很好的支持Ajax。

七、AJAX開發
到這里,已經可以清楚的知道AJAX是什么,AJAX能做什么,AJAX什么地方不好。如果你覺得AJAX真的能給你的開發工作帶來改進的話,那么繼續看看怎么使用AJAX吧。

7.1、AJAX應用到的技術AJAX涉及到的7項技術中,個人認為Javascript、XMLHttpRequest、DOM、XML比較有用。

A、XMLHttpRequest對象XMLHttpRequest是XMLHTTP組件的對象,通過這個對象,AJAX可以像桌面應用程序一樣只同服務器進行數據層面的交換,而不用每次都刷新界面,也不用每次將數據處理的工作都交給服務器來做;這樣既減輕了服務器負擔又加快了響應速度、縮短了用戶等待的時間。

IE5.0開始,開發人員可以在Web頁面內部使用XMLHTTP ActiveX組件擴展自身的功能,不用從當前的Web頁面導航就可以直接傳輸數據到服務器或者從服務器接收數據。,Mozilla1.0以及NetScape7則是創建繼承XML的代理類XMLHttpRequest;對于大多數情況,XMLHttpRequest對象和XMLHTTP組件很相似,方法和屬性類似,只是部分屬性不同。

XMLHttpRequest對象初始化:

XMLHttpRequest對象的方法:

方法描述
abort()停止當前請求
getAllResponseHeaders()作為字符串返回完整的headers
getResponseHeader("headerLabel")作為字符串返回單個的header標簽
open("method","URL"[,asyncFlag[,"userName"[, "password"]]])設置未決的請求的目標 URL,方法,和其他參數
send(content)發送請求
setRequestHeader("label", "value")設置header并和請求一起發送

XMLHttpRequest對象的屬性:

屬性描述
onreadystatechange
狀態改變的事件觸發器
readyState對象狀態(integer):
0 = 未初始化
1 = 讀取中
2 = 已讀取
3 = 交互中
4 = 完成
responseText服務器進程返回數據的文本版本
responseXML服務器進程返回數據的兼容DOM的XML文檔對象
status服務器返回的狀態碼, 如:404 = "文件未找到" 、200 ="成功"
statusText服務器返回的狀態文本信息

B、JavascriptJavascript一直被定位為客戶端的腳本語言,應用最多的地方是表單數據的校驗。現在,可以通過Javascript操作XMLHttpRequest,來跟數據庫打交道。

C、DOMDOM(Document Object Model)是提供給HTML和XML使用的一組API,提供了文件的表述結構,并可以利用它改變其中的內容和可見物。腳本語言通過DOM才可以跟頁面進行交互。Web開發人員可操作及建立文件的屬性、方法以及事件都以對象來展現。比如,document就代表頁面對象本身。

D、XML通過XML(Extensible Markup Language),可以規范的定義結構化數據,是網上傳輸的數據和文檔符合統一的標準。用XML表述的數據和文檔,可以很容易的讓所有程序共享。

7.2、AJAX開發框架這里,我們通過一步步的解析,來形成一個發送和接收XMLHttpRequest請求的程序框架。AJAX實質上也是遵循Request/Server模式,所以這個框架基本的流程也是:對象初始化à發送請求à服務器接收à服務器返回à客戶端接收à修改客戶端頁面內容。只不過這個過程是異步的。

A、初始化對象并發出XMLHttpRequest請求為了讓Javascript可以向服務器發送HTTP請求,必須使用XMLHttpRequest對象。使用之前,要先將XMLHttpRequest對象實例化。之前說過,各個瀏覽器對這個實例化過程實現不同。IE以ActiveX控件的形式提供,而Mozilla等瀏覽器則直接以XMLHttpRequest類的形式提供。為了讓編寫的程序能夠跨瀏覽器運行,要這樣寫:

if (window.XMLHttpRequest) { // Mozilla, Safari, ...

http_request = new XMLHttpRequest();

} else if (window.ActiveXObject) { // IE

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

}

有些版本的Mozilla瀏覽器處理服務器返回的未包含XML mime-type頭部信息的內容時會出錯。因此,要確保返回的內容包含text/xml信息。

http_request = new XMLHttpRequest();

http_request.overrideMimeType('text/xml');

B、指定響應處理函數接下來要指定當服務器返回信息時客戶端的處理方式。只要將相應的處理函數名稱賦給XMLHttpRequest對象的onreadystatechange屬性就可以了。比如:

http_request.onreadystatechange = processRequest;

需要指出的時,這個函數名稱不加括號,不指定參數。也可以用Javascript即時定義函數的方式定義響應函數。比如:

http_request.onreadystatechange = function() {

};

C、發出HTTP請求指定響應處理函數之后,就可以向服務器發出HTTP請求了。這一步調用XMLHttpRequest對象的open和send方法。

http_request.open('GET', 'http://www.example.org/some.file', true);

http_request.send(null);

open的第一個參數是HTTP請求的方法,為Get、Post或者Head。

第二個參數是目標URL。基于安全考慮,這個URL只能是同網域的,否則會提示“沒有權限”的錯誤。這個URL可以是任何的URL,包括需要服務器解釋執行的頁面,不僅僅是靜態頁面。

第三個參數只是指定在等待服務器返回信息的時間內是否繼續執行下面的代碼。如果為True,則不會繼續執行,直到服務器返回信息。默認為True。

按照順序,open調用完畢之后要調用send方法。send的參數如果是以Post方式發出的話,可以是任何想傳給服務器的內容。不過,跟form一樣,如果要傳文件給服務器,必須先調用setRequestHeader方法,修改MIME類別。如下:

http_request.setRequestHeader(“Content-Type”,”application/x-www-form-urlencoded”);

D、處理服務器返回的信息在第二步我們已經指定了響應處理函數,這一步,來看看這個響應處理函數都應該做什么。

首先,它要檢查XMLHttpRequest對象的readyState值,判斷請求目前的狀態。參照前文的屬性表可以知道,readyState值為4的時候,代表服務器已經傳回所有的信息,可以開始處理信息并更新頁面內容了。如下:

if (http_request.readyState == 4) {

// 信息已經返回,可以開始處理

} else {

// 信息還沒有返回,等待

}

服務器返回信息后,還需要判斷返回的HTTP狀態碼,確定返回的頁面沒有錯誤。所有的狀態碼都可以在W3C的官方網站上查到。其中,200代表頁面正常。

if (http_request.status == 200) {

// 頁面正常,可以開始處理信息

} else {

// 頁面有問題

}

XMLHttpRequest對成功返回的信息有兩種處理方式:

responseText:將傳回的信息當字符串使用;

responseXML:將傳回的信息當XML文檔使用,可以用DOM處理。

E、一個初步的開發框架總結上面的步驟,我們整理出一個初步的可用的開發框架,供以后調用;這里,將服務器返回的信息用window.alert以字符串的形式顯示出來:

var http_request = false;

function send_request(url) {//初始化、指定處理函數、發送請求的函數

http_request = false;

//開始初始化XMLHttpRequest對象

if(window.XMLHttpRequest) { //Mozilla 瀏覽器

http_request = new XMLHttpRequest();

if (http_request.overrideMimeType) {//設置MiME類別

http_request.overrideMimeType("text/xml");

}

}

else if (window.ActiveXObject) { // IE瀏覽器

try {

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

} catch (e) {

try {

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

} catch (e) {}

}

}

if (!http_request) { // 異常,創建對象實例失敗

window.alert("不能創建XMLHttpRequest對象實例.");

return false;

}

http_request.onreadystatechange = processRequest;

// 確定發送請求的方式和URL以及是否同步執行下段代碼

http_request.open("GET", url, true);

http_request.send(null);

}

// 處理返回信息的函數

function processRequest() {

if (http_request.readyState == 4) { // 判斷對象狀態

if (http_request.status == 200) { // 信息已經成功返回,開始處理信息

alert(http_request.responseText);

} else { //頁面不正常

alert("您所請求的頁面有異常。");

}

}

}

7.3、簡單的示例接下來,我們利用上面的開發框架來做兩個簡單的應用。

A、數據校驗在用戶注冊的表單中,經常碰到要檢驗待注冊的用戶名是否唯一。傳統的做法是采用window.open的彈出窗口,或者window. showModalDialog的對話框。不過,這兩個都需要打開窗口。采用AJAX后,采用異步方式直接將參數提交到服務器,用window.alert將服務器返回的校驗信息顯示出來。代碼如下:

在之間增加一段form表單代碼:

form-code.jpg

在開發框架的基礎上再增加一個調用函數:

function userCheck() {

var f = document.form1;

var username = f.username.value;

if(username=="") {

window.alert("用戶名不能為空。");

f.username.focus();

return false;

}

else {

send_request('sample1_2.jsp?username='+username);

}

}

看看sample1_2.jsp做了什么:

]]>

String username = request.getParameter("username");

if("educhina".equals(username)) out.print("用戶名已經被注冊,請更換一個用戶名。");

else out.print("用戶名尚未被使用,您可以繼續。");

%>]]>

運行一下,嗯,沒有彈出窗口,沒有頁面刷新,跟預想的效果一樣。如果需要的話,可以在sample1_2.jsp中實現更復雜的功能。最后,只要將反饋信息打印出來就可以了。

示例1_1.jpg
示例1_2.jpg

B、級聯菜單我們在第五部分提到利用AJAX改進級聯菜單的設計。接下來,我們就演示一下如何“按需取數據”。

首先,在中間增加如下HTML代碼:

經理室

?

開發部

?

在框架的基礎上增加一個響應函數showRoles(obj):

//顯示部門下的崗位

function showRoles(obj) {

document.getElementById(obj).parentNode.style.display = "";

document.getElementById(obj).innerHTML = "正在讀取數據..."

currentPos = obj;

send_request("sample2_2.jsp?playPos="+obj);

}

修改框架的processRequest函數:

// 處理返回信息的函數

function processRequest() {

if (http_request.readyState == 4) { // 判斷對象狀態

if (http_request.status == 200) { // 信息已經成功返回,開始處理信息

document.getElementById(currentPos).innerHTML = http_request.responseText;

} else { //頁面不正常

alert("您所請求的頁面有異常。");

}

}

}

最后就是smaple2_2.jsp了:

]]>

String playPos = request.getParameter("playPos");

if("pos_1".equals(playPos))

out.print("  總經理
  副總經理");

else if("pos_2".equals(playPos))

out.println("  總工程師
  軟件工程師");

%>]]>
運行一下看看效果:

示例2_1.jpg示例2_2.jpg



————————————————————————————————————————
AJAX編寫用戶注冊實例及技術小結

  我所舉的這個例子是一個企業用戶注冊時的一個應用,當用戶注冊時檢查用戶名和企業名是否可用,以前的做法是在旁邊加一個按鈕,點擊“檢查”,就向服務器發出請求,然后等待……服務器返回信息,繼續操作。如果我們用Ajax技術來實現以上的操作則不必等待服務器返回信息,用戶輸入用戶名或企業名稱的時候,當輸入文本框失去焦點的時候,則會自動向服務器發出請求,用戶繼續做下面的操作,不必點擊“檢查”,也不必等待服務器返回信息,檢查與用戶操作是異步的,可同時進行。當服務器信息返回的時候,會自動在面頁相應位置顯示返回信息,不必刷新頁面,相當于局部刷新的效果。

  下面我們來看代碼吧。

  HTML頁面的完整代碼如下:

1<%@page language="java" contentType="text/html;charset=GBK"%>
2<script language="javascript" type="text/javascript">
3<!--
4/**//**Ajax 開始 by Alpha 2005-12-31*/
5
6 var http = getHTTPObject();
7
8 function handleHttpResponse(){
9  if(http.readyState == 4){
10  if(http.status == 200){
11   var xmlDocument = http.responseXML;
12    if(http.responseText!=""){
13     document.getElementById("showStr").style.display = "";
14      document.getElementById("userName").style.background= "#FF0000";
15      document.getElementById("showStr").innerText = http.responseText;
16    }else{
17     document.getElementById("userName").style.background= "#FFFFFF";
18     document.getElementById("showStr").style.display = "none";
19    }
20
21   }
22   else{
23    alert("你所請求的頁面發生異常,可能會影響你瀏覽該頁的信息!");
24    alert(http.status);
25   }
26  }
27 }
28
29 function handleHttpResponse1(){
30  if(http.readyState == 4){
31   if(http.status == 200){
32    var xmlDocument = http.responseXML;
33    if(http.responseText!=""){
34     document.getElementById("comNmStr").style.display = "";
35     document.getElementById("comNm").style.background= "#FF0000";
36     document.getElementById("comNmStr").innerText = http.responseText;
37    }else{
38     document.getElementById("comNm").style.background= "#FFFFFF";
39     document.getElementById("comNmStr").style.display = "none";
40    }
41
42   }
43   else{
44    alert("你所請求的頁面發生異常,可能會影響你瀏覽該頁的信息!");
45    alert(http.status);
46   }
47  }
48 }
49
50 function chkUser(){
51  var url = "/chkUserAndCom";
52  var name = document.getElementById("userName").value;
53  url += ("&userName="+name+"&oprate=chkUser");
54  http.open("GET",url,true);
55  http.onreadystatechange = handleHttpResponse;
56  http.send(null);
57  return ;
58 }
59 function chkComNm(){
60  var url = "/chkUserAndCom";
61  var name = document.getElementById("comNm").value;
62  url += ("&comName="+name+"&oprate=chkCom");
63  http.open("GET",url,true);
64  http.onreadystatechange = handleHttpResponse1;
65  http.send(null);
66  return ;
67 }
68
69 //該函數可以創建我們需要的XMLHttpRequest對象
70 function getHTTPObject(){
71  var xmlhttp = false;
72  if(window.XMLHttpRequest){
73   xmlhttp = new XMLHttpRequest();
74   if(xmlhttp.overrideMimeType){
75    xmlhttp.overrideMimeType('text/xml');
76   }
77  }
78  else{
79   try{
80    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
81   }catch(e){
82    try{
83     xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
84    }catch(E){
85     xmlhttp = false;
86    }
87   }
88  }
89  return xmlhttp;
90 }
91/**//**Ajax 結束*/
92
93//檢測表單
94function chkpassword()
95{
96 var m=document.form1;
97 if(len(m.password.value) > 20 || len(m.password.value) < 5 || !isStr(m.password.value))
98 {
99  document.getElementById("passwordStr").style.display = "";
100  document.getElementById("password").style.background= "#FF0000";
101  document.getElementById("passwordStr").innerText = "對不起,密碼必須為英文字母、數字或下劃線,長度為5~20!";
102 }
103 else
104 {
105  document.getElementById("password").style.background= "#FFFFFF";
106  document.getElementById("passwordStr").style.display = "none";
107 }
108}
109
110function chkconfirmPassword()
111{
112  var m=document.form1;
113  if (m.password.value != m.confirmPassword.value)
114  {
115   document.getElementById("confirmPasswordStr").style.display = "";
116   document.getElementById("confirmPassword").style.background= "#FF0000";
117   document.getElementById("confirmPasswordStr").innerText = "對不起,密碼與重復密碼不一致!";
118  }
119  else
120  {
121   document.getElementById("confirmPassword").style.background= "#FFFFFF";
122   document.getElementById("confirmPasswordStr").style.display = "none";
123  }
124}
125
126function checkfield()
127{
128 var m=document.form1;
129 if(m.userName.value.length==0)
130 {
131  alert("對不起,用戶名必須為英文字母、數字或下劃線,長度為5~20。");
132  m.userName.focus();
133  return false;
134 }
135 if(m.password.value.length==0)
136 {
137  alert("對不起,密碼必須為英文字母、數字或下劃線,長度為5~20。");
138  m.password.focus();
139  return false;
140 }
141 if (m.password.value != m.confirmPassword.value)
142 {
143  alert("對不起,密碼與重復密碼不一致!");
144  m.confirmPassword.focus();
145  return false;
146 }
147 if(m.comNm.value.length==0)
148 {
149  alert("對不起,企業名稱不能為空!!");
150  m.comNm.focus();
151  return false;
152 }
153 m.submit();
154}
155
156//-->
157</script>
158<body topmargin="0">
159<form name="form1" method="post" action="/Control?act=Register">
160<table width="100%">
161 <tr><td align="center">?<H2>Ajax 演示程序</H1></td></tr>
162 <tr><td align="center">????------ 企業注冊 By Alpha</td></tr>
163</table>
164
165<HR>
166 <table width="400" border="0" cellpadding="1" cellspacing="1" align="center" >
167 <tr>
168  <td><font color="red">*</font></td>
169  <td>用戶帳號:</td>
170  <td>
171   <input type="text" name="userName" maxlength="20" style="background:#FFFFFF" onBlur="chkUser()" value=""/>
172   <div id="showStr" style="background-color:#FF9900;display:none"></div>
173  </td>
174 </tr>
175 <tr>
176  <td><font color="red">*</font></td>
177  <td>企業名稱:</td>
178  <td>
179   <input type="text" name="comNm" maxlength="100" style="background:#FFFFFF" onBlur="chkComNm()" value=""/>
180   <div id="comNmStr" style="background-color:#FF9900;display:none"></div>
181
182  </td>
183 </tr>
184 <tr>
185  <td><font color="red">*</font></td>
186  <td>用戶密碼:</td>
187  <td><input type="password" name="password" maxlength="20" style="background:#FFFFFF" onBlur="chkpassword()"/>
188   <div id="passwordStr" style="background-color:#FF9900;display:none"></div>
189  </td>
190 </tr>
191 <tr>
192  <td><font color="red">*</font></td>
193  <td>確認密碼:</td>
194  <td><input type="password" name="confirmPassword" maxlength="20" style="background:#FFFFFF" onBlur="chkconfirmPassword()"/>
195   <div id="confirmPasswordStr" style="background-color:#FF9900;display:none"></div>
196  </td>
197 </tr>
198 </table>
199
200 <div align="center">
201  <input type="button" name="ok" value=" 確 定 " onclick="checkfield()">
202 ?
203  <input type="reset" name="reset" value=" 取 消 ">
204 </div>
205
206</form>
207</body>
208</html>

  用JavaScript來創建XMLHttpRequest 類向服務器發送一個HTTP請求后,接下來要決定當收到服務器的響應后,需要做什么。這需要告訴HTTP請求對象用哪一個JavaScript函數處理這個響應。可以將對象的onreadystatechange屬性設置為要使用的JavaScript的函數名,如下所示:xmlhttp_request.onreadystatechange =FunctionName;

  FunctionName是用JavaScript創建的函數名,注意不要寫成FunctionName(),當然我們也可以直接將JavaScript代碼創建在onreadystatechange之后。

  我們調用request.open()-它用服務器打開套接字頻道,使用一個HTTP動詞(GET或POST)作為第一個參數并且以數據提供者的URL作為第二個參數。request.open()的最后一個參數被設置為true-它指示該請求的異步特性。注意,該請求還沒有被提交。隨著對request.send()的調用,開始提交-這可以為POST提供任何必要的有效載荷。在使用異步請求時,我們必須使用request.onreadystatechanged屬性來分配請求的回調函數。(如果請求是同步的話,我們應該能夠在調用request.send之后立即處理結果,但是我們也有可能阻斷用戶,直到該請求完成為止。)

  我看再看看數據提供者的URL,url = "/chkUserAndCom",servlet如下:

1/**//*
2 * Created on 2005-12-31
3 *
4 * TODO To change the template for this generated file go to
5 * Window - Preferences - Java - Code Style - Code Templates
6 */
7package com.event;
8
9import javax.servlet.ServletException;
10import javax.servlet.http.HttpServletRequest;
11import javax.servlet.http.HttpServletResponse;
12
13import com.beans.EBaseInfo;
14
15/** *//**
16 * @author Alpha 2005-12-31
17 *
18 * <P>Ajax 演示---企業注冊時檢查企業用戶名和企業名稱</P>
19 *
20 * TODO To change the template for this generated type comment go to
21 * Window - Preferences - Java - Code Style - Code Templates
22 */
23public class CheckUserAndComNm {
24 private String msgStr = "";
25 protected void doGet(HttpServletRequest request,HttpServletResponse response)
26 throws ServletException
27 {
28
29  EComBaseInfo info=new EComBaseInfo();
30  String oprate=request.getParameter("oprate")).trim();
31  String userName=request.getParameter("userName");
32  String passWord=request.getParameter("password");
33  String comName=request.getParameter("comName");
34
35  try
36  {
37   if(oprate.equals("chkUser"))
38   {
39    response.setContentType("text/html;charset=GB2312");
40    if(userName.length()<5||userName.length()>20)
41    {
42     msgStr = "對不起,用戶名必須為字母、數字或下劃線,長度為5-20個字符!";
43    }
44    else
45    {
46     boolean bTmp=info.findUser(userName); //找查數據庫中有無該用戶名
47     if(bTmp)
48      msgStr ="對不起,此用戶名已經存在,請更換用戶名注冊!";
49     else
50      msgStr ="";
51    }
52    response.getWriter().write(msgStr);
53   }
54   else if(oprate.equals("chkCom"))
55   {
56    response.setContentType("text/html;charset=GB2312");
57    if(comName.length()<6||comName.length()>100)
58    {
59     msgStr = "對不起,公司名稱長度為6-100個字符(不包括字符內的空格)!";
60    }
61    else
62    {
63     boolean bTmp=info.findCom(comName); //找查數據庫中有無該企業名
64     if(bTmp)
65      msgStr ="對不起,此企業名稱已經存在,請更換企業名稱注冊!";
66     else
67      msgStr ="";
68    }
69    response.getWriter().write(msgStr);
70   
71   }
72  }
73  catch(Exception ex)
74  {
75  }
76  finally
77  {
78   request.setAttribute("url",url);
79  }
80 }
81
82 protected void doPost(HttpServletRequest request,HttpServletResponse response)
83 throws ServletException
84 {
85  doGet(request,response);
86 }
87}
88

  AJAX技術小結

  1. Ajax(Asynchronous JavaScript and XML)是一個結合了Java技術、XML、以及JavaScript的編程技術,可以讓你構建基于Java技術的Web應用,并打破了使用頁面重載的慣例。

  2. Ajax,異步JavaScript與XML,是使用客戶端腳本與Web服務器交換數據的Web應用開發方法。這樣,Web頁面不用打斷交互流程進行重新加裁,就可以動態地更新。使用Ajax,你可以創建接近本地桌面應用的,直接的、高可用的、更豐富的、更動態的Web用戶接口界面。

  3. 對于Mozilla﹑Netscape﹑Safari、Firefox等瀏覽器,創建XMLHttpRequest 方法如下:

xmlhttp_request = new XMLHttpRequest();

  4. IE等創建XMLHttpRequest 方法如下:

  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP") 

  或 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

  5. xmlhttp_request.open('GET', URL, true); xmlhttp_request.send(null);

  6. open()的第一個參數是HTTP請求方式—GET,POST或任何服務器所支持的您想調用的方式。 按照HTTP規范,該參數要大寫;否則,某些瀏覽器(如Firefox)可能無法處理請求。第二個參數是請求頁面的URL。第三個參數設置請求是否為異步模式。如果是TRUE,JavaScript函數將繼續執行,而不等待服務器響應。這就是"AJAX"中的"A"。

  Ajax技術運用的好的話,給我們的網頁增添了許多友好的效果,給用戶還來更好的感覺。Ajax是個好東西。



————————————————————————————————————————
利用AJAX技術開發應用程序實戰

   AJAX,一個異步JavaScript和XML的縮略詞,是當今快速發展的Web開發界十分熱門的技術。在這項新技術提供巨大能力的同時,它也燃發了在"Back"按鈕問題上的不容置疑的爭論。本文作者將向你解釋怎樣在真實世界中使用AJAX以及怎樣在一個工程中評估它的價值。在你讀完本文后,你就會明白什么是AJAX,在什么情況下,為什么以及怎樣使用這項技術。

一、 簡介

   AJAX,一個異步JavaScript和XML的縮略詞,是最近出來的技術詞語。異步意味著你可以經由超文本傳輸協議(HTTP)向一個服務器發出請求并且在等待該響應時繼續處理另外的數據。這就意味著,例如,你可以調用一個服務器端腳本來從一個數據庫中以XML方式檢索數據,把數據發送到存儲在一個數據庫的服務器腳本,或者簡單地裝載一個XML文件以填充你的Web站點而不需刷新該頁面。然而,在這項新技術提供巨大能力的同時,它也引起了在"Back"按鈕問題上的很多爭論。本文將幫助你確定在真實世界中何時使用AJAX是最佳選擇。

   首先,我假定你對縮略詞JavaScript和XML部分有一個基本了解。盡管你能通過AJAX請求任何類型的文本文件,但是我在此主要集中討論XML。我將解釋怎樣在真實世界中使用AJAX以及怎樣在一個工程中評估它的價值。在你讀完本文后,你將會明白什么是AJAX,在什么情況下,為什么以及怎樣使用這項技術。你將要學習,在保持給用戶提供直觀體驗的同時怎樣創建對象,發出請求以及定制響應。

   我已創建了一個適合于本文的示例工程(你可以下載源代碼)。這個示例實現了一個簡單的請求-它裝載一個包含頁面內容的XML文件并且分析數據以把它顯示在一個HTML頁面中。

二、 常規屬性和方法

   表1和2提供了一個屬性和方法的概述-它們為 Windows Internet Explorer 5,Mozilla,Netscape 7,Safari 1.2,和 Opera 等瀏覽器所支持。

   表1屬性

屬性 描述
onreadystatechange 當請求對象變化時該事件處理器激活。
readyState 返回指示對象的當前狀態的值。
responseText 來自服務器的響應串的版本。
responseXML 來自服務器的響應的DOM兼容的文檔對象。
status 來自服務器的響應的狀態碼。
statusText 以一個字符串形式返回的狀態消息。

   表2方法

方法 描述
Abort() 取消當前HTTP請求。
getAllResponseHeaders() 檢索所有的HTTP頭值。
getResponseHeader("headerLabel") 從響應體中檢索一個HTTP頭部的值。
open("method","URL"[,asyncFlag[,"userName"[,"password"]]]) 初始化一個MSXML2.XMLHTTP請求,并從該請求指定方法,URL和認證信息。
send(content) 發送一個HTTP請求到服務器并接收響應。
setRequestHeader("label", "value") 指定一個HTTP頭的名字。

三、 從哪里開始

   首先,你需要創建XML文件-后面我們對之進行請求并作為頁面內容進行分析。你正在請求的文件必須與目標工程駐留在相同的服務器上。

   下一步,創建發出請求的HTML文件。當頁面通過使用頁面主體中的onload方法進行加載時,該請求發生。接著,該文件需要一個有ID的div標簽,這樣當我們準備好要顯示內容時就可以對之進行 定位 。當你做完所有這些,你的頁面的主體看上去如下:

<body onload="makeRequest('xml/content.xml');">
<div id="copy"></div>
</body>

四、 創建請求對象

   為了創建請求對象,你必須檢查是否瀏覽器使用XMLHttpRequest或ActiveXObject。這兩個對象之間的主要區別在于使用它們的瀏覽器。Windows IE 5 及以上版本使用ActiveX對象;而Mozilla,Netscape 7,Opera和Safari 1.2及以上版本使用XMLHttpRequest對象。另外一個區別是你創建對象的方式:Opera,Mozilla,Netscape和Safari允許你簡單地調用該對象的構造器,但是Windows IE需要把對象的名字傳遞到ActiveX構造器中。下面是怎樣創建代碼來決定要使用哪個對象和怎樣創建它的示例:

if(window.XMLHttpRequest)
{ request = new XMLHttpRequest();}
else if(window.ActiveXObject)
{ request = new ActiveXObject("MSXML2.XMLHTTP");}

五、 發出請求

   現在既然你已經創建了你的請求對象,那么你已經為向服務器發出請求作了準備。創建一個到事件處理器的參考以聽取onreadystatechange事件。然后,該事件處理器方法將在狀態發生變化時作出響應。一旦我們完成請求,我們就開始創建這個方法。打開連接以GET或POST一個定制的URL-在此是一個content.xml,并且設置一個布爾定義-是否你想要進行異步調用。

   現在到了發出請求的時間了。在這個示例中,我使用了null,因為我們使用的是GET;為了使用POST,你需要使用下面這個方法發出一個查詢串:

request.onreadystatechange = onResponse;
request.open("GET". url, true);
request.send(null);

六、 定制加載和錯誤處理消息

   你為onreadystatechange方法創建的事件處理器正是集中進行加載和處理錯誤的場所。現在到了考慮用戶并針對他們與之交互的內容的狀態提供反饋的時候了。在這個實例中,我針對所有的裝載狀態代碼提供反饋,并且也對最經常發生的錯誤處理狀態代碼提供一些基本的反饋。為了顯示請求對象的當前狀態,readyState屬性包括顯示在下表中的一些值。

描述
0 未初始化,對象沒有用數據進行初始化。
1 裝載中,對象正在裝載它的數據。
2 裝載結束,對象完成了它的數據的裝載。
3 可交互,用戶能與對象交互了,盡管它還沒有裝載結束。
4 完成,對象已經完全被初始化。

   W3C中有很長的一串有關HTTP狀態代碼的定義。我選擇了兩個狀態代碼:

   ·200:請求成功了。
   ·404:服務器沒有找到與所請求的文件相匹配的任何東西。

   最后,我檢查任何另外的狀況代碼-它們將生成一個錯誤并提供一個一般錯誤信息。下面是一個代碼示例-你可以用之來處理這些情況。注意,我在定位我們前面在HTML文件的主體中創建的div ID并且對它應用裝載和/或錯誤信息-通過innerHTML方法-這個方法用于設置在div對象的開始和結束標簽之間的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)
{
// 添加一個定制消息或把用戶重定向到另外一個頁面
document.getElementById('copy').innerHTML = "File not found";
}
else
{document.getElementById('copy').innerHTML = "There was a problem retrieving the XML."; }
}

   當狀況代碼為200時,這意味著請求成功。下面開始進行響應了。

七、 分析響應

   當你準備好分析來自請求對象的響應時,真正的工作開始了。現在你可以用你請求的數據開始工作。僅為測試目的,在開發期間,可以使用responseText和responseXML屬性來顯示來自響應的原始數據。為了存取XML響應中的結點,首先使用你創建的請求對象,定位到responseXML屬性以檢索(你可能已經猜測出來)來自響應的XML。定位到documentElement-它檢索一個到XML響應的根結點的參考。

var response = request.responseXML.documentElement;

   現在既然你有了到響應的根結點的參考,那么你可以使用getElementsByTagName()以結點名字來檢索childNodes。下面一行用一個頭部的nodeName來定位一個childNode:

response.getElementsByTagName('header')[0].firstChild.data;

   使用firstChild.data可以允許你存取該元素中的文本:

response.getElementsByTagName('header')[0].firstChild.data;

   下面是怎樣創建這些代碼的完整的例子:

var response = request.responseXML.documentElement;
var header = response.getElementsByTagName('header')[0].firstChild.data;
document.getElementById('copy').innerHTML = header;

八、 需求分析

   現在既然你知道怎樣使用AJAX的基礎知識,那么下一步就是決定是否在一工程使用它。須記住的最重要的事情是,在你還沒有刷新頁面時你無法使用"Back"按鈕。為此,可以先專注于你的工程中的一小部分-它能夠從使用這種類型的交互中受益。例如,你可以創建一個表單-它在用戶每次輸入一個輸入字段或一個字母時查詢一個腳本以便進行實時校驗。你可以創建一個拖放頁面-在釋放一項時,它能夠把數據發送到一個腳本中并把該頁面的狀態保存到一個數據庫中。使用AJAX的理由毫無疑問是存在的;并且這種使用無論對開發者還是用戶都會帶來益處;這全依賴于具體的條件和執行情況。

   還有其它方法可用來解決"Back"按鈕的問題,例如使用Google Gmail-它現在能夠為你的操作提供一種撤消功能而不刷新該頁面。以后還會出現許多更具創造性的例子-它們將通過提供給開發者創建獨特實時的體驗的手段給用戶帶來更大的好處。

九、 結論

   盡管AJAX允許我們構建新的和改進的方式來與一個WEB頁面進行交互;但是作為開發者,我們需要牢記產品是不考慮技術的;它關心的是用戶以及其如何與用戶進行交互。沒有了用戶群,我們構建的工程毫無用處。基于這個標準,我們就能評估應該使用什么技術以及何時使用它們來創建對相應用戶有用的應用軟件。



————————————————————————————————————————


————————————————————————————————————————