l 一個實例javascript
在開始正式講解 Ajax以前,首先讓咱們先來看看Google Map使用Ajax改善其產品設計的效果。php
1. 在瀏覽器地址欄中輸入http://maps.google.com打開Google Map的界面。css
2. 在頁面頂端的搜索框中輸入「China」,單擊「Search」按鈕。html
3. 單擊地圖右上角的「Satellite」按鈕,切換到衛星界面。java
4. 調整地圖左上角的尺寸,方法或者縮小當前區域。能夠看到,地圖區域的圖象根據標尺的位置快速的變換。web
5. 按住鼠標左鍵,拖拽地圖,地圖區域的圖象隨着鼠標的移動而移動這個過程的圖象是實時更新的。效果以下圖所。ajax
由上能夠明顯的看出,當用戶拖動地圖進行操做的時候,Web頁上的地圖當即發生相應的變化,頁面卻沒有刷新,當按住鼠標左鍵移動地圖的時候,地圖跟着移動,這個過程是快速的,而期間用戶沒有想服務器提交表單或和單擊一個超連接。若是用傳統的Web應用程序交互思惟來理解,這個過程是難以理解的,這正是Ajax的魅力。數組
l什麼是Ajax?瀏覽器
在研究ajax以前首先讓咱們先來討論一個問題 ——什麼是Web 2.0 。聽到 Web 2.0 這個詞的時候,應該首先問一問 「Web 1.0 是什麼?」 雖然不多聽人提到 Web 1.0,實際上它指的就是具備徹底不一樣的請求和響應模型的傳統 Web。好比,到 hdu.edu.cn 網站上點擊一個按鈕。就會對服務器發送一個請求,而後響應再返回到瀏覽器。該請求不只僅是新內容和項目列表,而是另外一個完整的 HTML 頁面。所以當 Web 瀏覽器用新的 HTML 頁面重繪時,可能會看到閃爍或抖動。事實上,經過看到的每一個新頁面能夠清晰地看到請求和響應。
Web 2.0(在很大程度上)消除了這種看得見的往復交互。好比在 Google Maps 上,你能夠拖動地圖,放大和縮小,只有不多的重繪操做。固然這裏仍然有請求和響應,只不過都藏到了幕後。做爲用戶,體驗更加溫馨,感受很像桌面應用程序。這種新的感覺和範型就是當有人提到 Web 2.0 時您所體會到的。
須要關心的是如何使這些新的交互成爲可能。顯然,仍然須要發出請求和接收響應,但正是針對每次請求/響應交互的 HTML 重繪形成了緩慢、笨拙的 Web 交互的感覺。所以很清楚,咱們須要一種方法使發送的請求和接收的響應只 包含須要的數據而不是整個 HTML 頁面。唯一須要得到整個新 HTML 頁面的時候就是但願用戶看到 新頁面的時候。
但多數交互都是在已有頁面上增長細節、修改主體文本或者覆蓋原有數據。這些狀況下,Ajax 和 Web 2.0 方法容許在不 更新整個 HTML 頁面的狀況下發送和接收數據。對於那些常常上網的人,這種能力可讓您的應用程序感受更快、響應更及時,讓他們不時地光顧您的網站。安全
所以在這裏,咱們是時候能夠對ajax作出一個完整的解釋了,Adaptive Path公司的Jesse James Garrett這樣定義Ajax:
Ajax不是一種技術。實際上,它由幾種蓬勃發展的技術以新的強大方式組合而成。Ajax包含:
這很是好,但爲何要以Ajax命名呢?其實術語Ajax是由Jesse James Garrett創造的,他說它是「Asynchronous JavaScript + XML的簡寫」。
l Ajax工做原理
經過上述的定義,咱們應該已經知道Ajax的組成了,即他是由XHTML,XML,CSS,DOM,XMLHttpRequest,JavaScript等技術綜合而成的,然而,真正使用Ajax能實現異步通訊,要真正實現這種絢麗的奇蹟,必須很是熟悉一個JavaScript 對象,即 XMLHttpRequest。所以咱們要了解Ajax的工做原理,就要從理解XMLHttpRequest這個對象開始。
下面給出將要用於該對象的不多的幾個 方法和屬性。
·open():創建到服務器的新請求。
·send():向服務器發送請求。
·abort():退出當前請求。
·readyState:提供當前 HTML 的就緒狀態。
·responseText:服務器返回的請求響應文本。
‘onreadystatechange:回調方法
·responseXML:服務器返回的請求響應XML形式組織的文本。
下面咱們簡單的介紹一下這幾個方法的做用。
l 建立一個XMLHttpRequest
首先須要建立一個新變量並賦給它一個 XMLHttpRequest 對象實例。這在 JavaScript 中很簡單,只要對該對象名使用 new 關鍵字便可,以下代碼所示。
<script language="javascript" type="text/javascript">
var request = new XMLHttpRequest();
</script>
在 JavaScript 中用 var 建立一個變量,給它一個名字(如 「request」),而後賦給它一個新的 XMLHttpRequest 實例。此後就能夠在函數中使用該對象了。
錯誤處理
在實際上各類事情均可能出錯,而上面的代碼沒有提供任何錯誤處理。較好的辦法是建立該對象,並在出現問題時優雅地退出。好比,任何較早的瀏覽器都不支持 XMLHttpRequest,您須要讓這些用戶知道有些地方出了問題。下面js代碼經過建立getXMLHttpRequest()方法說明如何建立該對象。
代碼1:一個詳細的XMLHttpRequest對象的建立
<script language="javascript" type="text/javascript">
function getXMLHttpRequest(){
var request = false;
try {
request = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = false;
}
}
}
return request;
}
</script>
必定要理解這些步驟:
建立一個新變量 request 並賦值 false。後面將使用 false 做爲斷定條件,它表示尚未建立 XMLHttpRequest 對象。
·增長 try/catch 塊:
·嘗試建立 XMLHttpRequest 對象。
一、若是失敗(catch (failed))則保證 request 的值仍然爲 false。
二、檢查 request 是否仍爲 false(若是一切正常就不會是 false)。
·若是出現問題則request 返回 false。
此外,在上面的代碼中,咱們是否是注意到了一個問題,就是當request = new XMLHttpRequest();出現異常的時候,在catch語句中咱們用了request = new ActiveXObject("Msxml2.XMLHTTP");和request = new ActiveXObject("Microsoft.XMLHTTP");等語句進行對象獲取,這是針對IE瀏覽器而進行的操做,由於IE瀏覽器對 XMLHttpRequest 版本有不一樣的稱呼。事實上,它將其稱爲幾種 不一樣的東西。若是使用較新版本的 Internet Explorer,則須要使用對象 Msxml2.XMLHTTP,而較老版本的 Internet Explorer 則使用 Microsoft.XMLHTTP。咱們須要支持這兩種對象類型(同時還要支持非 Microsoft 瀏覽器)。
l 用 XMLHttpRequest 發送請求
獲得請求對象以後就能夠進入請求/響應循環了。記住,XMLHttpRequest 唯一的目的是讓您發送請求和接收響應。其餘一切都是 JavaScript、CSS 或頁面中其餘代碼的工做:改變用戶界面、切換圖像、解釋服務器返回的數據。準備好 XMLHttpRequest 以後,就能夠向服務器發送請求了。
Ajax 採用一種沙箱安全模型。所以,Ajax 代碼(具體來講就是 XMLHttpRequest 對象)只能對所在的同一個域發送請求。若是讓 Ajax 代碼在www.hdu.edu.cn 上運行,則必須 www.hdu.edu.cn 中運行的腳本發送請求。
設置服務器 URL
首先要肯定鏈接的服務器的 URL。這並非 Ajax 的特殊要求,但仍然是創建鏈接所必需的。多數應用程序中都會結合一些靜態數據和用戶處理的表單中的數據來構造該 URL。好比,下列 JavaScript 代碼獲取電話號碼字段的值並用其構造 URL。
代碼2: 創建請求 URL
<script language="javascript" type="text/javascript">
function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.jsp?phone=" + escape(phone);
}
</script>
首先,代碼建立了一個新變量 phone,並把 ID 爲 「phone」 的表單字段的值賦給它。下列代碼展現了這個表單的 XHTML,其中能夠看到 phone 字段及其 id 屬性。
代碼3: Break Neck Pizza 表單
<body>
<form action="POST">
<p>Enter your phone number:
<input type="text" size="14" name="phone" id="phone" onChange="getCustomerInfo();" />
</p>
<p>Your order will be delivered to:</p>
<div id="address"></div>
<p>Type your order in here:</p>
<p><textarea name="order" rows="6" cols="50" id="order"></textarea></p>
<p><input type="submit" value="Order Pizza" id="submit" /></p>
</form>
</body>
還要注意,當用戶輸入電話號碼或者改變電話號碼時,將觸發getCustomerInfo() 方法。該方法取得電話號碼並構造存儲在 url 變量中的 URL 字符串。因爲 Ajax 代碼是沙箱型的,於是只能鏈接到同一個域,實際上 URL 中不須要域名。該例中的腳本名爲 /cgi-local/lookupCustomer.jsp。最後,電話號碼做爲 GET 參數附加到該腳本中:"phone=" + escape(phone)。
打開請求
有了要鏈接的 URL 後就能夠配置請求了。能夠用 XMLHttpRequest 對象的 open() 方法來完成。該方法有五個參數:
·request-type :發送請求的類型。典型的值是 GET 或 POST ,但也能夠發送 HEAD 請求。
·url :要鏈接的 URL 。
·asynch :若是但願使用異步鏈接則爲 true ,不然爲 false 。該參數是可選的,默認爲 true 。
·username :若是須要身份驗證,則能夠在此指定用戶名。該可選參數沒有默認值。
·password :若是須要身份驗證,則能夠在此指定口令。該可選參數沒有默認值。
一般使用其中的前三個參數。事實上,即便須要異步鏈接,也應該指定第三個參數爲 「true」 。這是默認值,但堅持明確指定請求是異步的仍是同步的更容易理解。
將這些結合起來,一般會獲得 下列所示的一行代碼。
代碼 4 getCustomerInfo() 方法的改進:
function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", url, true);
}
open() 是打開嗎?
咱們對 open() 方法到底作什麼沒有達成一致。但它實際上並非 打開一個請求。若是監控 XHTML/Ajax 頁面及其鏈接腳本之間的網絡和數據傳遞,當調用 open() 方法時將看不到任何通訊。
一旦設置好了 URL ,其餘就簡單了。多數請求使用 GET 就夠了,再加上 URL ,這就是使用 open() 方法須要的所有內容了。
發送請求
一旦用 open() 配置好以後,就能夠發送請求了。幸運的是,發送請求的方法的名稱要比 open() 適當,它就是 send() 。
send() 只有一個參數,就是要發送的內容。可是在考慮這個方法以前,回想一下前面已經經過 URL 自己發送過數據了:
var url = "/cgi-local/lookupCustomer.jsp?phone=" + escape(phone);
雖然可使用 send() 發送數據,但也能經過 URL 自己發送數據。事實上, GET 請求(在典型的 Ajax 應用中大約佔 80% )中,用 URL 發送數據要容易得多。若是須要發送安全信息或 XML ,可能要考慮使用 send() 發送內容(關於如何使用POST方式安全的發送數據,請參考個人另一篇文章--POST方式發送ajax請求詳解 )。若是不須要經過 send() 傳遞數據,則只要傳遞 null 做爲該方法的參數便可。
代碼 5 getCustomerInfo() 方法的進一步改進:
function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", url, true);
request.send(null);
}
指定回調方法
如今咱們所作的只有不多一點是新的、革命性的或異步的。必須認可, open() 方法中 「true」 這個小小的關鍵字創建了異步請求。可是 Ajax 和 Web 2.0 最大的祕密是什麼呢?祕密就在於 XMLHttpRequest 的一個簡單屬性 onreadystatechange 。
首先必定要理解這些代碼中的流程(若是須要請回顧 代碼 5 )。創建其請求而後發出請求。此外,由於是異步請求,因此 JavaScript 方法(例子中的 getCustomerInfo() )不會等待服務器。所以代碼將繼續執行,就是說,將退出該方法而把控制返回給表單。用戶能夠繼續輸入信息,應用程序不會等待服務器。
這就提出了一個有趣的問題:服務器完成了請求以後會發生什麼?答案是什麼也不發生,至少對如今的代碼而言如此!顯然這樣不行,所以服務器在完成經過 XMLHttpRequest 發送給它的請求處理以後須要某種指示說明怎麼作。
如今 onreadystatechange 屬性該登場了。該屬性容許指定一個回調函數。回調容許服務器(猜獲得嗎?)反向調用 Web 頁面中的代碼。它也給了服務器必定程度的控制權,當服務器完成請求以後,會查看 XMLHttpRequest 對象,特別是 onreadystatechange 屬 性。而後調用該屬性指定的任何方法。之因此稱爲回調是由於服務器向網頁發起調用,不管網頁自己在作什麼。比方說,可能在用戶坐在椅子上手沒有碰鍵盤的時候 調用該方法,可是也可能在用戶輸入、移動鼠標、滾動屏幕或者點擊按鈕時調用該方法。它並不關心用戶在作什麼。 這就是稱之爲異步的緣由:用戶在一層上操做表單,而在另外一層上服務器響應請求並觸發 onreadystatechange 屬性指定的回調方法。
在 JavaScript 中引用函數
JavaScript 是一種弱類型的語言,能夠用變量引用任何東西。所以若是聲明瞭一個函數 updatePage() , JavaScript 也將該函數名看做是一個變量。換句話說,可用變量名 updatePage 在代碼中引用函數。
代碼 6. 設置回調方法
function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", url, true);
request.onreadystatechange = updatePage;
request.send(null);
}
須要特別注意的是該屬性在代碼中設置的位置 —— 它是在調用 send() 以前 設置的。發送請求以前必須設置該屬性,這樣服務器在回答完成請求以後才能查看該屬性。
如今剩下的就只有編寫 updatePage() 方法了。
代碼 7. 檢查就緒狀態
function updatePage() {
if (request.readyState == 4)
if (request.status == 200)
alert("Server is done!");
}
其中 request.readyState 是 HTTP 的就緒狀態,在這裏咱們大概須要瞭解這 5 種狀態,關於其詳細意義,咱們在這就不在作深刻研究了。
request.readyState == 0 :請求沒有發出(在調用 open() 以前)。
request.readyState == 1 :請求已經創建但尚未發出(調用 send() 以前)。
request.readyState == 2 :請求已經發出正在處理之中(這裏一般能夠從響應獲得內容頭部)。
request.readyState ==3 :請求已經處理,響應中一般有部分數據可用,可是服務器尚未完成響應。
request.readyState == 4 :響應已完成,能夠訪問服務器響應並使用它。
而接下來的 request.status 爲 HTTP 狀態碼,爲 200 的時候爲正常, 400 多的時候爲客戶端的錯誤, 500 多的時候爲服務器端的服務,若是您對這方面的知識感興趣,不妨能夠去借一些 HTTP 協議之類的書看看,這裏也不作深刻研究了。
l 讀取響應文本
當咱們成功作完上面的一切時,服務器最後給出了處理的響應,咱們能夠把響應的內容 以 responseText 或者 responseXML 形式組織返回給客戶端供其調用。 responseXML 的話,要涉及到對 XML 的操做,由於 jdk 自己對 XML 的操做比較弱,不過咱們能夠運用第三方的包 org.jdom (網上有的下載),若是你們有興趣,能夠本身去研究,這裏咱們簡單的給出一個 responseXML 的用法的例子
代碼 8. responseText 的簡單運用
function updatePage() {
if (request.readyState == 4) {
if (request.status == 200) {
var response = request.responseText.split("|");
document.getElementById("order").value = response[0];
document.getElementById("address").innerHTML = response[1].replace(/\n/g, "");
} else
alert("status is " + request.status);
}
}
到如今,相信你們必定對 Ajax 有了一個系統的瞭解了吧,僅僅只是講了 Ajax 的一些最基礎的東西,若是您對這個有興趣,還能夠進行進一步的深刻研究。
l Ajax 應用場景
然而 Ajax 不是萬能的,在適合的場合使用 Ajax ,才能充分發揮它的長處,改善系統性能和用戶體驗,毫不能夠爲了技術而濫用。 Ajax 的特色在於異步交互,動態更新 web 頁面,所以它的適用範圍是交互較多,頻繁讀取數據的 web 應用。如今來看幾個 Ajax 的應用實例,讀者能夠了解如何使用 Ajax 技術改進現有的 web 應用系統。
場景 1. 數據驗證
在填寫表單內容時,需 要保證數據的惟一性(例如新用戶註冊填寫的用戶名),所以必須對用戶輸入的內容進行數據驗證。數據驗證一般有兩種方式:一種是直接填寫,而後提交表單,這 種方式須要將這個頁面提交到服務器端進行驗證,整個過程不只時間長並且形成了服務器沒必要要的負擔;第二種方式是改進了的驗證過程,用戶能夠經過點擊相應的 驗證按鈕,打開新窗口查看驗證結果,可是這樣須要新開一個瀏覽器窗口或者對話框,還須要專門編寫驗證的頁面,比較耗費系統資源。而使用 Ajax 技術,能夠由 XMLHttpRequest 對象發出驗證請求,根據返回的 HTTP 響應判斷驗證是否成功,整個過程不須要彈出新窗口,也不須要將整個頁面提交到服務器,快速而又不加劇服務器負擔。
場景 2. 按需取數據
分類樹或者樹形結構在 web 應用系統中使用得很是普遍,例如部門結構,文檔得分類結構經常使用樹形空間呈現。之前每次對分類樹得操做都會引發頁面重載,爲了不這種狀況出現,通常不採用每次調用後臺得方式,而是一次性將分類結果中得數據一次性讀取出來並寫入數組,而後根據用戶的操做,用 JavaScript 來 控制節點的呈現,這樣雖然解決了操做響應速度,不重複載入頁面以及避免向服務器頻繁發送請求的問題,可是若是用戶不對分類進行操做或者只對分類樹中的一部 分數據進行操做的話(這種狀況很廣泛的),那麼讀取的數據中就會有至關大的冗餘,浪費了用戶的資源。特別是在分類結構複雜,數據龐大的狀況下,這種弊端就 更加明顯了。
如今應用 Ajax 改進分類樹的實現機制。在初始化頁面時,只獲取第一級子分類的數據而且顯示;當用戶點開一級分類的第一節點時,頁面會經過 Ajax 向 服務器請求當前分類所屬的二級子分類的全部數據;若是再請求已經呈現的二級分類的某一節點時,再次向服務器請求當前分類所屬的三級子分類的全部數據,以此 類推。頁面會根據用戶的操做向服務器請求它所須要的數據,這樣就不會存在數據的冗餘,減小了數據下載總量。同時,更新頁面時不須要重載全部內容,只更新需 要更新的那部份內容便可,相對於之前後臺處理而且重載的方式,大大縮短了用戶的等待時間。
場景 3. 自動更新頁面
在 web 應用中有不少數據的變化時十分迅速的,例如最新的熱點新聞,天氣預報以及聊天室內容等。在 Ajax 出 現以前,用戶爲了即便了解相應的內容必須不斷刷新頁面,查看是否有新的內容變化,或者頁面自己實現定時刷新的功能(大多數聊天室頁面就是這樣作的)。有可 能會發生這種狀況;有一段時間網頁的內容沒有發生任何變化,可是用戶並不知道,仍然不斷的刷新頁面;或者用戶失去了耐心,放棄了刷新頁面,卻頗有可能在此 有新的消息出現,這樣就錯過了第一時間獲得消息的機會。
應用 Ajax 能夠改善這種這種狀況,頁面加載之後,會經過 Ajax 引擎在後臺進行定時的輪詢,向服務器發送請求,查看是否有最新的消息。若是有則將新的數據(而不是全部數據)下載而且在頁面上進行動態的更新,經過必定的方式通知用戶(實現這樣的功能正是 JavaScript 的強項)。這樣即避免了用戶不斷手工刷新頁面的不便,也不會由於重複刷新頁面形成資源浪費。
轉載:http://www.cnblogs.com/jevonsea/archive/2011/05/23/2054330.html