AJAX的實現步驟(完整過程)
AJAX全稱為“Asynchronous JavaScript and XML”(非同步JavaScript和XML),是一種建立互動式網頁應用的網頁開發技術。Ajax的工作原理相當於在使用者和伺服器之間加了—箇中間層(AJAX引擎),使使用者操作與伺服器響應非同步化。並不是所有的使用者請求都提交給伺服器,像—些資料驗證和資料處理等都交給Ajax引擎自己來做, 只有確定需要從伺服器讀取新資料時再由Ajax引擎代為向伺服器提交請求。
實現一個AJAX非同步呼叫和區域性重新整理,通常需要以下幾個步驟:
建立XMLHttpRequest物件,也就是建立一個非同步呼叫物件.
建立一個新的HTTP請求,並指定該HTTP請求的方法、URL及驗證資訊.
設定響應HTTP請求狀態變化的函式.
傳送HTTP請求.
獲取非同步呼叫返回的資料.
使用JavaScript和DOM實現區域性重新整理.
實現步驟如下:
1、建立XMLHttpRequest物件
不同的瀏覽器使用的非同步呼叫物件也有所不同,在IE瀏覽器中非同步呼叫使用的是XMLHTTP元件中的XMLHttpRequest物件,而在Netscape、Firefox瀏覽器中則直接使用XMLHttpRequest元件。因此,在不同瀏覽器中建立XMLHttpRequest物件的方式都有所不同.
在IE瀏覽器中建立XMLHttpRequest物件的方式如下所示:
var xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
在Netscape瀏覽器中建立XMLHttpRequest物件的方式如下所示:
var xmlHttpRequest = new XMLHttpRequest();
由於無法確定使用者使用的是什麼瀏覽器,所以在建立XMLHttpRequest物件時,最好將以上兩種方法都加上.如以下程式碼所示:
<script language = "javascript" type = "text/javascript"> var xmlHttpRequest; //定義一個變數,用於存放XMLHttpRequest物件 function createXMLHttpRequest() //建立XMLHttpRequest物件的方法 { if(window.ActiveXObject) //判斷是否是IE瀏覽器 { xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP"); //建立IE瀏覽器中的XMLHttpRequest物件 } else if(window.XMLHttpRequest) //判斷是否是Netscape等其他支援XMLHttpRequest元件的瀏覽器 { xmlHttpRequest = new XMLHttpRequest(); //建立其他瀏覽器上的XMLHttpRequest物件 } } </script> createXMLHttpRequst(); //呼叫建立物件的方法
"if(window.ActiveXObject)"用來判斷是否使用IE瀏覽器.其中ActiveXOject並不是Windows物件的標準屬性,而是IE瀏覽器中專有的屬性,可以用於判斷瀏覽器是否支援ActiveX控制元件.通常只有IE瀏覽器或以IE瀏覽器為核心的瀏覽器才能支援Active控制元件.
"else if(window.XMLHttpRequest)"是為了防止一些瀏覽器既不支援ActiveX控制元件,也不支援XMLHttpRequest元件而進行的判斷.其中XMLHttpRequest也不是window物件的標準屬性,但可以用來判斷瀏覽器是否支援XMLHttpRequest元件.
如果瀏覽器既不支援ActiveX控制元件,也不支援XMLHttpRequest元件,那麼就不會對xmlHttpRequest變數賦值.
2、建立HTTP請求
建立了XMLHttpRequest物件之後,必須為XMLHttpRequest物件建立HTTP請求,用於說明XMLHttpRequest物件要從哪裡獲取資料.通常可以是網站中的資料,也可以是本地中其他檔案中的資料.
建立HTTP請求可以使用XMLHttpRequest物件的open()方法,其語法程式碼如下所示:
XMLHttpRequest.open(method,URL,flag,name,password)
程式碼中的引數解釋如下所示:
method:該引數用於指定HTTP的請求方法,一共有get、post、head、put、delete五種方法,常用的方法為get和post。
URL:該引數用於指定HTTP請求的URL地址,可以是絕對URL,也可以是相對URL。
flag:該引數為可選引數,引數值為布林型。該引數用於指定是否使用非同步方式。true表示非同步方式、false表示同步方式,預設為true。
name:該引數為可選引數,用於輸入使用者名稱。如果伺服器需要驗證,則必須使用該引數。
password:該引數為可選引數,用於輸入密碼。如果伺服器需要驗證,則必須使用該引數。通常可以使用以下程式碼來訪問一個網站檔案的內容。
xmlHttpRequest.open("get","http://www.aspxfans.com/BookSupport/JavaScript/ajax.htm",true);
或者使用以下程式碼來訪問一個本地檔案內容:
xmlHttpRequest.open("get","ajax.htm",true);
注意:如果HTML檔案放在Web伺服器上,在Netscape瀏覽器中的JavaScript安全機制不允許與本機之外的主機進行通訊。也就是說,使用open()方法只能開啟與HTML檔案在同一個伺服器上的檔案。而在IE瀏覽器中則無此限制(雖然可以開啟其他伺服器上的檔案,但也會有警告提示)。
3、設定響應HTTP請求狀態變化的函式
建立完HTTP請求之後,應該就可以將HTTP請求傳送給Web伺服器了。然而,傳送HTTP請求的目的是為了接收從伺服器中返回的資料。從建立XMLHttpRequest物件開始,到傳送資料、接收資料、XMLHttpRequest物件一共會經歷以下5中狀態。
⑴未初始化狀態。在建立完XMLHttpRequest物件時,該物件處於未初始化狀態,此時XMLHttpRequest物件的readyState屬性值為0。
⑵初始化狀態。在建立完XMLHttpRequest物件後使用open()方法建立了HTTP請求時,該物件處於初始化狀態。此時XMLHttpRequest物件的readyState屬性值為1。
⑶傳送資料狀態。在初始化XMLHttpRequest物件後,使用send()方法傳送資料時,該物件處於傳送資料狀態,此時XMLHttpRequest物件的readyState屬性值為2。
⑷接收資料狀態。Web伺服器接收完資料並進行處理完畢之後,向客戶端傳送返回的結果。此時,XMLHttpRequest物件處於接收資料狀態,XMLHttpRequest物件的readyState屬性值為3。
⑸完成狀態。XMLHttpRequest物件接收資料完畢後,進入完成狀態,此時XMLHttpRequest物件的readyState屬性值為4。此時接收完畢後的資料存入在客戶端計算機的記憶體中,可以使用responseText屬性或responseXml屬性來獲取資料。
只有在XMLHttpRequest物件完成了以上5個步驟之後,才可以獲取從伺服器端返回的資料。因此,如果要獲得從伺服器端返回的資料,就必須要先判斷XMLHttpRequest物件的狀態。
XMLHttpRequest物件可以響應readystatechange事件,該事件在XMLHttpRequest物件狀態改變時(也就是readyState屬性值改變時)激發。因此,可以通過該事件呼叫一個函式,並在該函式中判斷XMLHttpRequest物件的readyState屬性值。如果readyState屬性值為4則使用responseText屬性或responseXml屬性來獲取資料。具體程式碼如下所示:
//設定當XMLHttpRequest物件狀態改變時呼叫的函式,注意函式名後面不要新增小括號
xmlHttpRequest.onreadystatechange = getData;
//定義函式
function getData()
{
//判斷XMLHttpRequest物件的readyState屬性值是否為4,如果為4表示非同步呼叫完成
if(xmlHttpRequest.readyState == 4)
{
//設定獲取資料的語句
}
}
4、設定獲取伺服器返回資料的語句
如果XMLHttpRequest物件的readyState屬性值等於4,表示非同步呼叫過程完畢,就可以通過XMLHttpRequest物件的responseText屬性或responseXml屬性來獲取資料。
但是,非同步呼叫過程完畢,並不代表非同步呼叫成功了,如果要判斷非同步呼叫是否成功,還要判斷XMLHttpRequest物件的status屬性值,只有該屬性值為200,才表示非同步呼叫成功,因此,要獲取伺服器返回資料的語句,還必須要先判斷XMLHttpRequest物件的status屬性值是否等於200,如以下程式碼所示:
if(xmlHttpRequst.status == 200)
{
//使用以下語句將返回結果以字串形式輸出
document.write(xmlHttpRequest.responseText);
//或者使用以下語句將返回結果以XML形式輸出
//document.write(xmlHttpRequest.responseXML);
}
注意:如果HTML檔案不是在Web伺服器上執行,而是在本地執行,則xmlHttpRequest.status的返回值為0。因此,如果該檔案在本地執行,則應該加上xmlHttpRequest.status == 0的判斷。
通常將以上程式碼放在響應HTTP請求狀態變化的函式體內,如以下程式碼所示:
//設定當XMLHttpRequest物件狀態改變時呼叫的函式,注意函式名後面不要新增小括號
xmlHttpRequest.onreadystatechange = getData;
//定義函式
function getData()
{
//判斷XMLHttpRequest物件的readyState屬性值是否為4,如果為4表示非同步呼叫完成
if(xmlHttpRequest.readyState==4)
{
//設定獲取資料的語句 state=200說明伺服器成功響應返回的結果是正確的
if(xmlHttpRequest.status == 200 || xmlHttpRequest.status == 0)
{
//使用以下語句將返回結果以字串形式輸出
document.write(xmlHttpRequest.responseText);
//或者使用以下語句將返回結果以XML形式輸出
//docunment.write(xmlHttpRequest.responseXML);
}
}
}
5、傳送HTTP請求
在經過以上幾個步驟的設定之後,就可以將HTTP請求傳送到Web伺服器上去了。傳送HTTP請求可以使用XMLHttpRequest物件的send()方法,其語法程式碼如下所示:
XMLHttpRequest.send(data)
其中data是個可選引數,如果是get請求的資料寫在url中,那這裡即可以使用null來替代。如果是post請求,data引數的格式與在URL中傳遞引數的格式類似,以下程式碼為一個send()方法中的data引數的示例:
name=myName&value=myValue
另外,get和post請求傳送請求的程式碼實現還有以下區別:
get請求需要防止客戶端和伺服器互動過程亂編碼問題,注意在伺服器配置編碼格式或者把get請求的url用encodeURI方法處理轉換為utf-8,而post則預設是utf-8編碼,伺服器端預設是IOS-8859-1,如果也遇到亂碼問題,則在伺服器端設定如下程式碼:
request.setCharacterEncoding("utf-8");
而且根據http協議要求post請求需要額外設定請求頭,如下:
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
只有在使用send()方法之後,XMLHttpRequest物件的readyState屬性值才會開始改變,也才會激發readystatechange事件,並呼叫函式。
6、區域性更新
在通過Ajax的非同步呼叫獲得伺服器端資料之後,可以使用JavaScript或DOM來將網頁中的資料進行區域性更新。常用的區域性更新的方式有以下3種:
⑴表單物件的資料更新
表單物件的資料更新,通常只要更改表單物件的value屬性值,其語法程式碼如下所示:
FormObject.value = "新數值"
有關表單物件的資料更新的示例如以下程式碼所示:
<html>
<head>
<title>區域性更新</title>
<script language = "javascript" type = "text/javascript">
<!--
function changeData()
{
document.myForm.myText.value = "更新後的資料"
}
-->
</head>
<body>
<form name = "myForm">
<input type = "text" value = "原資料" name = "myText">
<input type = "button" value = "更新資料" onclick = "changeData()">
</form>
</body>
</html>
⑶DOM技術的區域性重新整理
innerText和innerHTML兩個屬性都是IE瀏覽器中的屬性,在Netscape瀏覽器中並不支援該屬性。但無論是IE瀏覽器還是Netscape瀏覽器,都支援DOM。在DOM中,可以修改標籤間的文字內容。
在DOM中,將HTML文件中的每一對開始標籤和結束標籤都看成是一個節點。例如HTML文件中有一個標籤如下所示,那麼該標籤在DOM中稱之為一個“節點”。
<div id = "myDiv">原資料</div>
在DOM中使用getElementById()方法可以通過id屬性值來查詢該標籤(或者說是節點),如以下語句所示:
var node = document.getElementById("myDiv");
注意:在一個HTML文件中,每個標籤中的id屬性值是不能重複的。因此,使用getElementById()方法獲得的節點是唯一的。
在DOM中,認為開始標籤與結束標籤之間的文字是該節點的子節點,而firstChild屬性可以獲得一個節點下的第1個子節點。如以下程式碼可以獲得<div>節點下的第1個子節點,也就是<div>標籤與</div>標籤之間的文位元組點。
node.firstChild
注意,以上程式碼獲得的是文位元組點,而不是文字內容。如果要獲得節點的文字內容,則要使用節點的nodeValue屬性。通過設定nodeValue屬性值,可以改變文位元組點的文字內容。完整的程式碼如下所示:
<html>
<head>
<title>區域性更新</title>
<script language = "javascript" type = "text/javascript">
<!--
function changeData()
{
//查詢標籤(節點)
var node = document.getElementById("myDiv");
//在DOM中標籤中的文字被認為是標籤中的子節點
//節點的firstChild屬性為該節點下的第1個子節點
//nodeValue屬性為節點的值,也就是標籤中的文字值
node.firstChild.nodeValue = "更新後的資料";
}
-->
</script>
</head>
</html>
注意:目前主流的瀏覽器都支援DOM技術的區域性重新整理。
7、完整的AJAX例項
<html>
<head>
<title>AJAX例項</title>
<script language="javascript" type="text/javascript">
<!--
var xmlHttpRequest; //定義一個變數用於存放XMLHttpRequest物件
//定義一個用於建立XMLHttpRequest物件的函式
function createXMLHttpRequest()
{
if(window.ActiveXObject)
{
//IE瀏覽器的建立方式
xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}else if(windew.XMLHttpRequest)
{
//Netscape瀏覽器中的建立方式
xmlHttpRequest = new XMLHttpRequest();
}
}
//響應HTTP請求狀態變化的函式
function httpStateChange()
{
//判斷非同步呼叫是否完成
if(xmlHttpRequest.readyState == 4)
{
//判斷非同步呼叫是否成功,如果成功開始區域性更新資料
if(xmlHttpRequest.status == 200||xmlHttpRequest.status == 0)
{
//查詢節點
var node = document.getElementById("myDIv");
//更新資料
node.firstChild.nodeValue = xmlHttpRequest .responseText;
}
else
{
//如果非同步呼叫未成功,彈出警告框,並顯示出錯資訊
alert("非同步調用出錯/n返回的HTTP狀態碼為:"+xmlHttpRequest.status + "/n返回的HTTP狀態資訊為:" + xmlHttpRequest.statusText);
}
}
}
//非同步呼叫伺服器段資料
function getData(name,value)
{
//建立XMLHttpRequest物件
createXMLHttpRequest();
if(xmlHttpRequest!=null)
{
//建立HTTP請求
xmlHttpRequest.open("get","ajax.text",true)
//設定HTTP請求狀態變化的函式
xmlHttpRequest.onreadystatechange = httpStateChange;
//傳送請求
xmlHttpRequest.send(null);
}
}
-->
</script>
</head>
<body>
<div id="myDiv">原資料</div>
<input type = "button" value = "更新資料" onclick = "getData()">
</body>
</html>