Ajax基本原理
摘要:本文介紹了Ajax的基本原理,交互過(guò)程和與之相關(guān)的技術(shù)及簡(jiǎn)單的實(shí)現(xiàn)方法,在此基礎(chǔ)上給出了一個(gè)完整的實(shí)例,以使得能夠?qū)jax有一個(gè)更清楚的理解。
關(guān)鍵字:Ajax,JavaScript,DOM,無(wú)刷新頁(yè)面,不完全刷新
引言
計(jì)算機(jī)桌面應(yīng)用使我們得以用以前不能想象的方式處理大量的復(fù)雜數(shù)據(jù);基于計(jì)算機(jī)網(wǎng)絡(luò)的C/S模式應(yīng)用使得共享數(shù)據(jù)和資源成為現(xiàn)實(shí)。然而,正如C/S模式的應(yīng)用是由于人們不滿足單機(jī)的桌面應(yīng)用一樣,人們對(duì)C/S模式也心存抱怨了:C/S模式除了帶給我們數(shù)據(jù)和資源共享的便利之外,也給我們帶來(lái)了令我們(程序開發(fā)設(shè)計(jì)人員)和客戶頭疼的部署和發(fā)布問題。于是,B/S模式應(yīng)用應(yīng)運(yùn)而生,而且得到了迅速的發(fā)展。B/S模式應(yīng)用符合一定規(guī)范的瀏覽器作為通用客戶端,從而解決了C/S模式中最令人頭疼的部署和發(fā)布問題。但是,到此并沒有結(jié)束,B/S雖然解決了應(yīng)用的部署和發(fā)布問題,卻因?yàn)榉N種限制,使得應(yīng)用沒有了以前豐富的交互,并且每次與服務(wù)器的交互都要完全刷新頁(yè)面,這是非常糟糕和令人不快的。本文討論了如何解決頁(yè)面完全刷新和缺乏交互性的問題,我們用的方法就是――Ajax。
Ajax
那么,Ajax到底是什么呢?Ajax(Asynchronous JavaScript + XML),即異步JavaScript + XML的縮寫,這只是最初的觀點(diǎn),最初由Jesse James Garrett創(chuàng)造出來(lái)的。但是,Ajax現(xiàn)在的覆蓋面已經(jīng)有了進(jìn)一步的擴(kuò)展,把允許瀏覽器與服務(wù)器通信而無(wú)需刷新當(dāng)前頁(yè)面的技術(shù)都涵蓋在其中了。
坦率的講,Ajax并不是什么新鮮玩藝。也就是說(shuō),Ajax并不是一種全新的技術(shù),而更像一種技巧,是把過(guò)去的幾種技術(shù)巧妙結(jié)合的技巧。真正與Ajax相關(guān)的新名詞應(yīng)該是XMLHttpRequest――一個(gè)最早在IE 5中出現(xiàn),最近開始在多數(shù)瀏覽器得到支持的用來(lái)實(shí)現(xiàn)異步通信的對(duì)象。正如前面所說(shuō),B/S模式是利用瀏覽器作為其通用的客戶端,所以要想異步通訊成為可能,必須要得到瀏覽器的支持。如果不是有了瀏覽器對(duì)XMLHttpRequest對(duì)象的廣泛支持,我們可能不會(huì)看到Ajax的今天,更不會(huì)看到許多對(duì)Ajax的著名應(yīng)用,如Google Map,Google Suggest,Ta-da List等。
Ajax的處理過(guò)程是怎樣的呢?下 數(shù)
圖為Ajax應(yīng)用的標(biāo)準(zhǔn)處理模式。
圖 1 標(biāo)準(zhǔn)Ajax處理過(guò)程
從圖中我們可以看出:由事件觸發(fā),創(chuàng)建一個(gè)XMLHttpRequest對(duì)象,把HTTP方法(Get/Post)和目標(biāo)URL以及請(qǐng)求返回后的回調(diào)函數(shù)設(shè)置到XMLHttpRequest對(duì)象,通過(guò)XMLHttpRequest向服務(wù)器發(fā)送請(qǐng)求,請(qǐng)求發(fā)送后繼續(xù)響應(yīng)用戶的界面交互,只有等到請(qǐng)求真正從服務(wù)器返回的時(shí)候才調(diào)用callback()函數(shù),對(duì)響應(yīng)數(shù)據(jù)進(jìn)行處理。
在這個(gè)交互過(guò)程中,涉及到幾種我們不得不提的技術(shù):
1. XHTML和CSS――用來(lái)使表現(xiàn)標(biāo)準(zhǔn)化;
2.DOM――動(dòng)態(tài)的修改文檔的內(nèi)容和結(jié)構(gòu);
3.XML――進(jìn)行數(shù)據(jù)的交換和處理;
4.JavaScript――對(duì)上述幾種技術(shù)進(jìn)行綁定,使其成為協(xié)同工作的整體。
Ajax相關(guān)技術(shù)及基本原理
1. XMLHttpRequest簡(jiǎn)介
XMLHttpRequest,是我們得以實(shí)現(xiàn)異步通訊的根本。最早在IE 5 中以ActiveX組件實(shí)現(xiàn);最近,Mozilla 1.0和Safari 1.2中實(shí)現(xiàn)為本地對(duì)象。XMLHttpRequest雖然不是W3C標(biāo)準(zhǔn),但卻得到了FireFox、Safari、Opera、Konqueror、IE等絕大多數(shù)瀏覽器的支持。這就使得Ajax有了今天如火如荼的發(fā)展。
用XMLHttpRequest進(jìn)行異步通訊,首先必須用JavaScript創(chuàng)建一個(gè)XMLHttpRequest對(duì)象實(shí)例。創(chuàng)建XMLHttpRequest對(duì)象實(shí)例的代碼清單如下所示:
var xmlHttp;
function createXMLHttpRequest(){
if(window.ActiveXObject){
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest){
xmlHttp = new XMLHttpRequest();
}
}
可以看出,創(chuàng)建XMLHttpRequest對(duì)象相當(dāng)容易。首先,聲明一個(gè)全局變量xmlHttp用來(lái)保存即將創(chuàng)建的XMLHttpRequest對(duì)象的引用;然后,在createXMLHttpRequest()方法中完成具體創(chuàng)建工作。因?yàn)镮E與其他瀏覽器對(duì)XMLHttpRequest 對(duì)象的實(shí)現(xiàn)方法不同,因此在創(chuàng)建時(shí),通過(guò)一個(gè)分支語(yǔ)句進(jìn)行判斷。如果window.ActiveXObject調(diào)用返回true,則證明為IE瀏覽器,那么就通過(guò)傳遞“Microsoft.XMLHTTP”給ActiveXObject()來(lái)創(chuàng)建XMLHttpRequest對(duì)象,否則就把XMLHttpRequest實(shí)現(xiàn)為本地JavaScript對(duì)象。XMLHttpRequest對(duì)象在不同瀏覽器上的實(shí)現(xiàn)是兼容的,所以可以用同樣的方法訪問XMLHttpRequest的方法和屬性。
表 1 標(biāo)準(zhǔn)XMLHttpRequest方法
方 法
說(shuō) 明
abort()
getAllResponseHeader()
getResponseHeader("Header")
open("method", "url")
send(content)
setRequestHeader("header", "value")
停止當(dāng)前請(qǐng)求
把HTTP請(qǐng)求的所有響應(yīng)頭部作為鍵/值對(duì)返回
返回指定首部的串值
建立對(duì)服務(wù)器的調(diào)用
向服務(wù)器發(fā)送請(qǐng)求
把指定首部設(shè)置為所提供的值
表 2 標(biāo)準(zhǔn)XMLHttpRequest屬性
屬 性
說(shuō) 明
onreadystatechange
readyState
responseText
responseXML
status
statusText
每個(gè)狀態(tài)改變都會(huì)觸發(fā)這個(gè)事件處理器
請(qǐng)求的狀態(tài):0-未初始化,1-正在加載,2-已加載,3-交互中,4-完成
服務(wù)器的響應(yīng),表示為一個(gè)文本字符串值
服務(wù)器的響應(yīng),表示為一個(gè)XML
服務(wù)器的HTTP狀態(tài)碼
HTTP狀態(tài)碼的相應(yīng)文本
2. 利用XMLHttpRequest對(duì)象發(fā)送簡(jiǎn)單請(qǐng)求
創(chuàng)建了XMLHttpRequest對(duì)象,并了解了XMLHttpRequest對(duì)象的方法和屬性之后,讓我們來(lái)看看怎樣利用XMLHttpRequest對(duì)象發(fā)送簡(jiǎn)單的請(qǐng)求。利用XMLHttpRequest對(duì)象發(fā)送簡(jiǎn)單請(qǐng)求的基本步驟如下:
1) 創(chuàng)建XMLHttpRequest對(duì)象實(shí)例。
2) 設(shè)定XMLHttpRequest對(duì)象的回調(diào)函數(shù),利用onreadystatechange屬性。
3) 設(shè)定請(qǐng)求屬性:設(shè)定HTTP方法(GET或POST);設(shè)定目標(biāo)URL。利用open()方法。
4) 將請(qǐng)求發(fā)送給服務(wù)器。利用send()方法。
3. 利用DOM對(duì)服務(wù)器響應(yīng)進(jìn)行處理
前面已經(jīng)設(shè)置了回調(diào)函數(shù),回調(diào)函數(shù)正是用來(lái)處理服務(wù)器響應(yīng)信息的。但是,別忘了我們的最終目的:解決頁(yè)面完全刷新和缺乏交互性的問題。在服務(wù)器對(duì)我們的請(qǐng)求信息作出響應(yīng)后,我們就得實(shí)現(xiàn)頁(yè)面的無(wú)縫更新(就是無(wú)閃爍的更新信息)。要實(shí)現(xiàn)這一點(diǎn),那么就不得不提到DOM了。
DOM(Document Object Model),文檔對(duì)象模型,是以面向?qū)ο蠓绞矫枋鲰?yè)面文檔的對(duì)象模型。DOM中定義了,與平臺(tái)和語(yǔ)言無(wú)關(guān)的,用來(lái)表示和修改文檔所需的對(duì)象、以及這些對(duì)象的屬性和方法。通過(guò)DOM,我們可以把頁(yè)面上的數(shù)據(jù)和結(jié)構(gòu)抽象成一個(gè)樹型表示,進(jìn)而可以通過(guò)DOM中定義的屬性和方法對(duì)文檔進(jìn)行操作,如遍歷、編輯等。
這樣,服務(wù)器相應(yīng)信息就可以通過(guò)DOM的方法和屬性,動(dòng)態(tài)的更新到頁(yè)面的相應(yīng)節(jié)點(diǎn)。
從而使用戶感覺不到刷新過(guò)程的存在,提高了交互性。
4. 一個(gè)完整的例子
在這里我們給出一個(gè)完整的利用Ajax的實(shí)例。實(shí)例包含兩個(gè)文件:Request.htm和Response.xml。通過(guò)Request.htm向服務(wù)器發(fā)送請(qǐng)求,而Response.xml模仿了從服務(wù)器返回的響應(yīng)。兩個(gè)文件清單如下:
<!--Request.htm----------------------------------------------------------->
<html>
<head>
<title>Ajax應(yīng)用實(shí)例</title>
<script type="text/javaScript">
var xmlHttp;
var requestType="";
function createXMLHttpRequest(){
if(window.ActiveXObject){
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest){
xmlHttp = new XMLHttpRequest();
}
}
function startRequest(theRequestType){
requestType = theRequestType;
createXMLHttpRequest();
xmlHttp.onreadystatechange = handleStateChange;
xmlHttp.open("GET","Response.xml",true);
xmlHttp.send(null);
}
function myCallback(){
if(xmlHttp.readyState==4){
if(xmlHttp.status==200){
if(requestType=="all")
listAll();
else if(requestType=="north")
listNorth();
}
}
}
function listAll(){
var xmlDoc = xmlHttp.responseXML;
var allProvs = xmlDoc.getElementsByTagName("prov");
outputList("all",allProvs);
}
function listNorth(){
var xmlDoc = xmlHttp.responseXML;
var north = xmlDoc.getElementsByTagName("north")[0];
var northProvs = north.getElementsByTagname("prov");
outputList("north",northProvs);
}
function outputList(title,provs){
var out=title;
var currentProv = null;
for(var i=0;i<provs.length;i++){
currentProv = provs[i];
out = out + “<br/>” + currentProv.childNodes[0].nodeValue;
}
document.getElementById(title).innerHTML = out;
}
</script>
</head>
<body>
<h1> Ajax應(yīng)用實(shí)例</h1>
<form action="#">
<input type="button" value="列出所有沿海省市"
conclick="startRequest('all'); "/>
<div id="all"></div>
<input type="button" value="列出江北沿海省市"
conclick="startRequest('north'); "/>
<div id="north"></div>
</form>
</body>
</html>
<!--Response.xml---------------------------------------------------------->
<?xml version="1.0"encoding="utf-8" ?>
<provs>
<north>
<prov>遼寧</prov><prov>河北</prov><prov>天津</prov>
<prov>山東</prov><prov>江蘇</prov>
</north>
<south>
<prov>浙江</prov><prov>福建</prov><prov>廣東</prov>
<prov>廣西</prov><prov>海南</prov><prov>上海</prov>
<prov>臺(tái)灣</prov><prov>香港</prov><prov>澳門</prov>
</south>
</provs>
小結(jié)
我們已經(jīng)了解了Ajax的基本原理和相關(guān)的技術(shù)。其實(shí),Ajax就是通過(guò)JavaScript創(chuàng)建XMLHttpRequest對(duì)象,再由JavaScript調(diào)用XMLHttpRequest對(duì)象的方法完成異步通信;然后,再由JavaScript通過(guò)DOM的屬性和方法,完成頁(yè)面的不完全刷新。
如有看不清楚。。請(qǐng)將它復(fù)制到一個(gè)word文檔里面