Ajax 如何將笨拙的 Web 界面轉化成能迅速響應的 Ajax 應用程序。
ajax功能
就是不需要刷新整個頁面就可以更新數據,不用像以前一樣所有負擔都壓在服務器上,實現與后端的數據獲取。
Ajax 用 JavaScript 把 XMLHttpRequest 對象放在 Web 表單和服務器之間。
當填寫表單時,數據》》》》 JavaScript 代碼 (不是 直接發送給服務器) 。
相反,JavaScript 代碼捕獲表單數據》》》》》服務器發送請求。
JavaScript 代碼在幕后發送請求,用戶甚至不知道請求的發出。更好的是,請求是異步發送的,就是說 JavaScript 代碼(和用戶)不用等待服務器的響應。
XMLHttpRequest 對象
XMLHttpRequest 對象,它是 Ajax 應用程序的中心,負責處理服務器端應用程序和腳本的請求,并處理從服務器端組件返回的數據。所以所有的 Ajax 應用程序都要使用 XMLHttpRequest 對象
創建新的 XMLHttpRequest 對象
<script language="javascript" type="text/javascript">
var xmlHttp = new XMLHttpRequest();
</script>
兼容性問題
var xmlHttp = false;
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e2) {
xmlHttp = false;
}
}
if (!xmlHttp && typeof XMLHttpRequest != 'undefined') {
xmlHttp = new XMLHttpRequest();
}
用 JavaScript 代碼捕獲和設置字段值
document.getElementById("oneId").value;
so 要用到 DOM
啟動一個 Ajax 過程
<form>
<p>City: <input type="text" name="city" id="city" size="25"
onChange="callServer();" /></p>
</form>
當用戶在 city 或 state 字段中輸入新的值時,callServer() 方法就被觸發,于是 Ajax 開始運行了。
發出請求
Ajax 采用一種沙箱安全模型。因此,Ajax 代碼(具體來說就是 XMLHttpRequest 對象)只能對所在的同一個域發送請求,不能跨域。在本地機器上運行的代碼只能對本地機器上的服務器端腳本發送請求。如果讓 Ajax 代碼在 http://www.breakneckpizza.com/ 上運行,則必須 http://www.breakneck.com/ 中運行的腳本發送請求。
設置服務器 URL
首先要確定連接的服務器的 URL。這并不是 Ajax 的特殊要求,但仍然是建立連接所必需的,顯然現在你應該知道如何構造 URL 了。多數應用程序中都會結合一些靜態數據和用戶處理的表單中的數據來構造該 URL。
1、從 Web 表單中獲取需要的數據。
2、建立要連接的 URL。
3、打開到服務器的連接。
4、設置服務器在完成后要運行的函數。
5、發送請求。
function callServer() {
//使用基本 JavaScript 代碼獲取幾個表單字段的值
var city = document.getElementById("city").value;
var state = document.getElementById("state").value;
if ((city == null) || (city == "")) return;
if ((state == null) || (state == "")) return;
//設置一個 PHP 腳本作為鏈接的目標
var url = "/scripts/getZipCode.php?city=" + escape(city) + "&state=" + escape(state);
// 連接方法(GET) 要連接的 URL true表示請求一個異步連接(這就是 Ajax 的由來)。false就要等服務器返回結果
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}
escape() 方法,它用于轉義不能用明文正確發送的任何字符。
document.write(escape("Visit W3School.com.cn!") + "<br />")
可以根據需要添加任意多個參數。比如,如果需要增加另一個參數,只需要將其附加到 URL 中并用 “與”(&)字符分開 [第一個參數用問號(?)和腳本名分開]。
打開請求
有了要連接的 URL 后就可以配置請求了。可以用 XMLHttpRequest 對象的 open() 方法來完成。該方法有五個參數:
1.request-type:發送請求的類型。典型的值是 GET 或 POST,
2.url:要連接的 URL。
3.asynch:如果希望使用異步連接則為 true,否則為 false。該參數是可選的,默認為 true。
4.username:如果需要身份驗證,則可以在此指定用戶名。該可選參數沒有默認值。
5.password:如果需要身份驗證,則可以在此指定口令。該可選參數沒有默認值。
send(null)
因為需要的數據已經在url里了所以就為null;
處理響應
現在要面對服務器的響應了。現在只要知道兩點:
什么也不要做,直到 xmlHttp.readyState 屬性的值等于 4。
服務器將把響應填充到 xmlHttp.responseText 屬性中。
第二點,使用 xmlHttp.responseText 屬性獲得服務器的響應,
function updatePage() {
if (xmlHttp.readyState == 4) {
//如果是就緒狀態,則使用服務器返回的值設置另一個表單字段的值。
var response = xmlHttp.responseText;
document.getElementById("zipCode").value = response;
}
}
指定回調方法
首先一定要理解這些代碼中的流程。建立其請求然后發出請求。此外,因為是異步請求,所以 JavaScript 方法(例子中的 getCustomerInfo())不會等待服務器。因此代碼將繼續執行,就是說,將退出該方法而把控制返回給表單。用戶可以繼續輸入信息,應用程序不會等待服務器。
這就提出了一個有趣的問題:服務器完成了請求之后會發生什么?答案是什么也不發生,至少對現在的代碼而言如此!顯然這樣不行,因此服務器在完成通過 XMLHttpRequest 發送給它的請求處理之后需要某種指示說明怎么做。
需要特別注意的是該屬性在代碼中設置的位置 —— 它是在調用 send() 之前 設置的。發送請求之前必須設置該屬性,這樣服務器在回答完成請求之后才能查看該屬性。現在剩下的就只有編寫 updatePage() 方法了,這是本文最后一節要討論的重點。
處理服務器響應
服務器查看 onreadystatechange 屬性確定要調用的方法,讓用戶訪問另一個 URL 或者做響應服務器需要的任何事情。
回調和 Ajax
現在我們已經看到如何告訴服務器完成后應該做什么:將 XMLHttpRequest 對象的 onreadystatechange 屬性設置為要運行的函數名。這樣,當服務器處理完請求后就會自動調用該函數。也不需要擔心該函數的任何參數。我們從一個簡單的方法開始,
回調方法的代碼
<script language="javascript" type="text/javascript">
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;
}
}
}
if (!request)
alert("Error initializing XMLHttpRequest!");
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;
//在 JavaScript 中引用函數:
JavaScript 是一種弱類型的語言,可以用變量引用任何東西。因此如果聲明了一個函數 updatePage(),JavaScript 也將該函數名看作是一個變量。換句話說,可用變量名 updatePage 在代碼中引用函數。
request.send(null);
}
function updatePage() {
alert("Server is done!");
}
</script>
它僅僅發出一些簡單的警告,告訴你服務器什么時候完成了任務。在自己的網頁中試驗這些代碼,然后在瀏覽器中打開輸入電話號碼然后離開該字段,將看到一個彈出的警告窗口,但是點擊 OK 又出現了……
根據瀏覽器的不同,在表單停止彈出警告之前會看到兩次、三次甚至四次警告。這是怎么回事呢?原來我們還沒有考慮 HTTP 就緒狀態,這是請求/響應循環中的一個重要部分。
HTTP 就緒狀態
前面提到,服務器在完成請求之后會在 XMLHttpRequest 的 onreadystatechange 屬性中查找要調用的方法。這是真的,但還不完整。事實上,每當 HTTP 就緒狀態改變時它都會調用該方法。這意味著什么呢?首先必須理解 HTTP 就緒狀態。
HTTP 就緒狀態表示請求的狀態或情形。它用于確定該請求是否已經開始、是否得到了響應或者請求/響應模型是否已經完成。它還可以幫助確定讀取服務器提供的響應文本或數據是否安全。在 Ajax 應用程序中需要了解五種就緒狀態:
. 0:請求沒有發出(在調用 open() 之前)。
·1:請求已經建立但還沒有發出(調用 send() 之前)。
·2:請求已經發出正在處理之中(這里通常可以從響應得到內容頭部)。
·3:請求已經處理,響應中通常有部分數據可用,但是服務器還沒有完成響應。
·4:響應已完成,可以訪問服務器響應并使用它。
查看就緒狀態
function updatePage() {
// Output the current ready state
alert("updatePage() called with ready state of " + request.readyState);
}
對于 Ajax 編程,需要直接處理的惟一狀態就是就緒狀態 4,它表示服務器響應已經完成,可以安全地使用響應數據了。基于此,回調方法中的第一行應該如
檢查就緒狀態
function updatePage() {
if (request.readyState == 4)
alert("Server is done!");
}
修改后就可以保證服務器的處理已經完成。嘗試運行新版本的 Ajax 代碼,現在就會看到與預期的一樣,只顯示一次警告信息了。
可以在就緒狀態發生變化時更新頁面。
例如,對于就緒狀態 1 來說要將進度指示器的寬度設置為 25%,對于就緒狀態 2 來說要將進度指示器的寬度設置為 50%,對于就緒狀態 3 來說要將進度指示器的寬度設置為 75%,當就緒狀態為 4 時將進度指示器的寬度設置為 100%(完成)。
HTTP 狀態碼
·401:未經授權
·403:禁止
·404:沒找到
.200:一切正常
重定向和重新路由
—— 重定向。在 HTTP 狀態代碼中,這是 300 系列的狀態代碼,包括:
·301:永久移動
·302:找到(請求被重新定向到另外一個 URL/URI 上)
·305:使用代理(請求必須使用一個代理來訪問所請求的資源)
因此除了就緒狀態外,還需要檢查 HTTP 狀態。我們期望的狀態碼是 200,它表示一切順利。如果就緒狀態是 4 而且狀態碼是 200,就可以處理服務器的數據了,而且這些數據應該就是要求的數據(而不是錯誤或者其他有問題的信息)。因此還要在回調方法中增加狀態檢查.
檢查 HTTP 狀態碼
function updatePage() {
if (request.readyState == 4)
if (request.status == 200)
alert("Server is done!");
}
function updatePage() {
if (request.readyState == 4)
if (request.status == 200)
alert("Server is done!");
else if (request.status == 404)
alert("Request URL does not exist");
else
alert("Error: status code is " + request.status);
}
讀取響應文本
現在可以確保請求已經處理完成(通過就緒狀態4),服務器給出了正常的響應(通過狀態碼200),最后我們可以處理服務器返回的數據了。返回的數據保存在 XMLHttpRequest 對象的 responseText 屬性中。
關于 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);
}
}
JavaScript split() 方法從管道符分開。得到的數組放到 response 中。數組中的第一個值用 response[0] 訪問,被設置為 ID 為 “order” 的字段的值。第二個值 response[1],即客戶地址,則需要更多一點處理。因為地址中的行用一般的行分隔符(“\n”字符)分隔,代碼中需要用 XHTML 風格的行分隔符 <br /> 來代替。替換過程使用 replace() 函數和正則表達式完成。最后,修改后的文本作為 HTML 表單 div 中的內部 HTML。結果就是表單突然用客戶信息更新了,
使用 Ajax 生成一個 HEAD 請求
function getSalesData() {
createRequest();
var url = "/boards/servlet/UpdateBoardSales";
request.open("HEAD", url, true);
request.onreadystatechange = updatePage;
request.send(null);
}
當生成一個 HEAD 請求時,服務器并不會像對 GET 或 POST 請求一樣返回一個真正的響應。相反,服務器只會返回資源的 頭(header),這包括響應中內容最后修改的時間、請求資源是否存在和很多其他有用信息。可以在服務器處理并返回資源之前使用這些信息來了解有關資源的信息。
對于這種請求可以做的最簡單的事情就是簡單地輸出所有的響應頭的內容。這可以讓你了解通過 HEAD 請求可以使用什么
輸出從 HEAD 請求中獲得的響應頭的內容
function updatePage() {
if (request.readyState == 4) {
alert(request.getAllResponseHeaders());
}
}
檢查 URL(沒毛線用)
有用的 HEAD 請求
你會發現 HEAD 請求非常有用的一個領域是用來查看內容的長度或內容的類型。這樣可以確定是否需要發回大量數據來處理請求,和服務器是否試圖返回二進制數據,而不是 HTML、文本或 XML(在 JavaScript 中,這 3 種類型的數據都比二進制數據更容易處理)。
在這些情況中,你只使用了適當的頭名,并將其傳遞給 XMLHttpRequest 對象的 getResponseHeader() 方法。因此要獲取響應的長度,只需要調用 request.getResponseHeader("Content-Length");。要獲取內容類型,請使用 request.getResponseHeader("Content-Type");。
在很多應用程序中,生成 HEAD 請求并沒有增加任何功能,甚至可能會導致請求速度變慢(通過強制生成一個 HEAD 請求來獲取有關響應的數據,然后在使用一個 GET 或 POST 請求來真正獲取響應)。然而,在出現你不確定有關腳本或服務器端組件的情況時,使用 HEAD 請求可以獲取一些基本的數據,而不需要對響應數據真正進行處理,也不需要大量的帶寬來發送響應。
利用 DOM 進行 Web 響應
..............................
..............................
..............................
這個太大了,我也說不全 自己嘗試吧