AJAX是什麼
AJAX = Asynchronous JavaScript and XML(異步的 JavaScript 和 XML)。
AJAX 不是新的編程語言,而是一種使用現有標準的新方法。
AJAX 最大的優點是在不重新加載整個頁面的情況下,可以與服務器交換數據並更新部分網頁內容。
AJAX 不需要任何瀏覽器插件,但需要用戶允許JavaScript在瀏覽器上執行。
先來看看爲什麼要用ajax,瞭解同步和異步是什麼:
同步的意思就是客戶端提交表單,發起請求後需要一直等待服務器端的響應,收到服務器端的響應後需要重新載入頁面。
而有了ajax,則可進行異步交互,比如不會提交整個表單後等待服務器響應再刷新頁面,而是填寫的過程中,通過ajax的機制,就可以把已經填寫的部分提交給服務器,服務器進行處理,而這個過程中可以繼續填寫後面的內容,服務器發送迴響應只會刷新頁面的部分內容(利用JavaScript操作DOM進行局部刷新),而不是重新載入整個頁面。
其實就是爲客戶機(網頁中常爲JavaScript)代碼提供了一種發送HTTP請求的方式。通常提交請求都是以表單的形式發送,獲取響應要刷新整頁,而ajax則是按需發送,只刷新返回的數據。
Ajax指異步的JavaScript和XML,JS無需等待服務器響應,而是在繼續執行腳本內容,響應就緒後對響應進行處理。若是同步,則JS代碼會收到服務器的響應後再繼續執行。
ajax是通過XMLHttpRequest對象在客戶端和服務器端進行數據交換的。
1. 創建XMLHttpRequest對象
該對象用於和服務器交換數據:
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
2.向服務器發送請求
XHR.open(method,url,async):規定請求的方式、請求文件在服務 器上的URL和是否異步處理請求。啓動一個請求以備發送。
Method:get和post(post用來傳輸數據)
url:要發送請求的地址;
async:聲明發送的請求的方法(true、false)
XHR.send():將請求發送到服務器,參數爲請求主體發送的數據,如果不需要請求主體發送數據,則必須填入null,因爲對有些瀏覽器來說必須有一個參數。通常post方式會填入發送的數據。
3.服務器響應
在收到響應後,響應的數據會自動填充XHR對象的屬性:
XHR.responseText:服務器返回的文本數據
XHR.responseXML:服務器返回的XML格式的數據
status:服務器返回的狀態碼。響應的HTTP狀態:
- 200: “OK”,響應成功返回
- 304:請求的資源未被修改,可使用瀏覽器中的緩存版本
- 404: 未找到頁面
statusText:HTTP狀態文本說明
同步的時候應當檢查status的值後來決定下一步的操作:
if(xhr.status>=200 && xhr.status<300 || xhr.status=304){
//do something
}else{
alert("request was unsuccessful: "+xhr.status);
}
4.異步處理
onreadystatechange 事件:當async爲true時,規定該事件上綁定的方法,每當readyState屬性改變時,就會觸發該事件。
readyState屬性:表示請求-響應過程的當前活動階段。爲XHR對象的狀態。異步的時候應當檢查該屬性。從 0 到 4 發生變化:
0: 請求未初始化,未調用open()
1: 服務器連接已建立,已調用open,未調用send
2: 請求已接收,即服務器已收到請求頭信息。 已調用send,尚未收到響應
3: 已收到部分響應數據
4: 請求已完成,已收到全部響應數據,可在客戶端使用
注意:需在調用open之前指定onreadystatechange事件綁定的函數才能確保跨瀏覽器兼容性。
xhr.onreadystatechange=function(){
if(xhr.readyStatus==4){
if(xhr.status>=200 && xhr.status<300 || xhr.status==304){
//do something
}else{
alert("request was unsuccessful: "+xhr.status);
}
}
}
5.終止異步
xhr.abort():調用該方法取消異步請求,XHR對象會停止觸發事件,並且不再允許訪問任何與響應有關的對象屬性。
在終止請求後,應對XHR對象釋放引用。
6.老版本的XHR對象缺點
只支持文本數據的傳送,無法讀取和上傳二進制文件。
只能訪問同域中的資源。
傳送和接收數據時沒有進度信息,只能提示有無完成。
新版本即level2的改進:
瀏覽器在發送XHR請求的同時也會默認發送一些頭部信息,瀏覽器能夠顯示的字符集(Accept-charset)、當前頁面設置的任何Cookie等。也可以自定義發送信息,通過調用XHR.setRequestHeader(header,value)向請求添加頭部。該方法應當放在open之後send之前。
XHR對象的getResponseHeader()和getAllResponseHeaders()可用於獲取響應的頭部信息
1. GET請求
常用於向服務器查詢某些信息,可將查詢字符串參數追加到url末尾。必須對查詢字符串進行encodeURIComponent()編碼,具體來說必須對參數名和參數值都進行編碼才能附加到url後面。
向現有url追加查詢字符串參數:
functionaddURLPara(url,name,value){
url += (url.indexOf("?") == -1 ? "?":"&");
url += encodeURIComponent(name)+"="+encodeURIComponent(value);
return url;
}
2.POST請求
用於向服務器發送應當被保存的數據(修改服務器端數據),數據是請求的主體。
使用POST方式:
- 無法使用緩存文件(get通常會使用緩存?)
- 向服務器發送大量數據
- 發送包含未知字符的用戶輸入
在send方法中傳入要發送的數據(字符串或文檔)
表單數據序列化,通過XHR發送到服務器:
functionsubmitData(){
var xhr = createXHR();
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status>=200 && xhr.status<300 || xhr.status==304){
//do something
}else{
alert("request was unsuccessful: "+xhr.status);
}
};
}
xhr.open("post","url",true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); //表單提交時的內容類型,如果提交的是表單數據必須要寫這個
var form = document.getElementById("user-info");
xhr.send(serialize(form));//表單序列化
}
使用該方式必須設置自定義請求頭部信息Content-Type,以說明請求的內容類型。這樣服務器就會根據請求的內容類型來解析表單中的數據。
在通過post方式請求表單中,在open和send之間,要添加request.setRequestHeader(“Content-Type”,”application/x-www-form-urlencoded”)
如果不設置content-type頭部,那麼發送給服務器的數據就不會出現在$_POST超級全局變量中。
在來看看新一代的XHR即XHR2級對象又提供了哪些方法吧。
1. FormData類型
用於將表單數據序列化和創建和表單格式相同的數據:
方式一:
var data = new FormData();
data.append(“key”,”value”);
方式二:
var data = new FormData(form對象);
以上代碼應該在open和send(data)之間。
2. overrideMimeType(“text/xml”)方法
重寫服務器返回的MIME類型。強迫XHR對象將響應當做XML而非純文本來處理
3.超時設定(IE8+支持)
XHR對象支持timeout屬性和ontimeout事件處理程序。timeout屬性用於設置請求等待響應的時間,若超出了則終止請求,然後觸發timeout事件,調用ontimeout事件處理程序。
終止請求後readyState屬性可能已經爲4了,但是如果終止請求後再訪問status屬性(響應狀態碼)會報錯,因此可將訪問該屬性的代碼用try、catch括起來。
那麼我們通過XHR對象傳遞的數據都有哪些格式呢?下面再來看看常用的幾種數據格式。
XML是一種數據格式,在異步應用程序中常有以下兩種用法:
一是以XML格式從網頁發送HTTP請求給服務器
二是以XML格式在網頁中接收服務器的響應
客戶端發送請求
XML格式的請求和響應比普通文本慢,消耗內存更多,因爲要添加標籤和語義。
將數據包裝爲XML格式其實也是使用字符串的形式,不過字符串中有相應的標籤。即發送的數據都必須是文本。
以XML格式化數據時應先設置請求頭部:
xhr.setRequestHeader(“Content-type”,”text/xml”)。若果是發送普通文本則類型爲text/plain
最好是使用普通文本的方式發送請求數據。
發送文本格式的請求(名/值對)和發送XML格式包裝後的數據例子講解:http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro7.html
服務器發送響應
比較適合用XML格式的數據,原因是若發送的響應爲文本,其中包含多個名稱/值對,服務器程序用某種符號連接這些對兒(沒有一個標準),而客戶端必須採取措施將這些響應文本(字符串)中的對兒依次解析出來。(而服務器端技術提供了多種方法來根據名稱獲取值,所以客戶端發送請求時適合用名稱/值對這種方式)。
XML響應可以是以XML格式化的純文本,客戶端中通過xhr.responseText屬性來獲取,這時仍出現了需要解析字符串的問題,所以不應該以這種方式來發送XML響應。應當使用XML文檔,客戶端可通過xhr.responseXML獲取,將該文檔當成一個DOM Document對象,在客戶端可以利用DOM來解析該文檔。
**json基本概念和格式
當需要在客戶端和服務器端之間傳遞大量數據時,使用Json格式的數據會很靈活,便於解析。
Json是一種存儲和交換文本信息的語法,採用鍵值對方式組織。Json是獨立於語言的,可被任何語言解析和生成。
json和XML相比有這樣一些優點:
長度短小,讀寫速度更快;可以使用JavaScript內建的方法進行解析,也可以直接轉換成JavaScript對象,非常方便。
json數據的書寫格式爲名稱-值這樣的對兒:
"name":value
· 1
注意名稱有引號,當value爲字符串時也應該加引號。
value的數據類型可爲:
· 數字
· 字符串
· 布爾值
· 數組(在[]中)
· 對象(在{}中)
· null
舉一個json文件的例子:
{
"staff":[
{"name":"anna"},
{"name":"mike","age":10},
{"name":"lily","age":30}
]
}
最外層的大括號{}表示這是一個json對象。
**在JS中解析json
通過下述幾種方式可以把一個json字符串解析爲一個JavaScript對象。
(1)使用eval()解析
可以瀏覽器控制檯中進行如下代碼測驗:
var jsondata='{"staff":[{"name":"anna","age":20},{"name":"mike","age":10},{"name":"lily","age":30}]}'; //注意這個json字符串要放到同一行;服務器端的返回的數據應該寫成這樣一個json對象字符串
var jsonobj=eval('('+jsondata+')'); //eval使用這種方式解析
alert(jsonobj.staff[0].name);
採用eval,不僅會解析成一個JavaScript對象,還會執行json字符串中的方法,例如把”age”:20改爲”age”:alert(“hello”),則會執行這個alert語句。
(2)使用JSON.parse()解析
var jsonobj=JSON.parse(jsondata);
· 1
使用這種方式解析不會執行json字符串中的方法,會報錯,json字符串語法不合法。
由於eval方法不會檢查語法,這樣很危險,如果接收的json數據中包含惡意代碼會被執行。
檢查json語法的格式化校驗在線工具:jsonlint.com
該事件的作用是提供了與文檔或元素的加載狀態有關的信息。支持該事件的對象都有一個readyState屬性。該屬性有如下幾個值:
uninitialized(未初始化):對象存在但尚未初始化
loading(正在加載):對象正在加載數據
loaded:對象加載數據完成
interactive:可以操作對象了,但韓沒有完全加載
complete:對象已經加載完畢
並非所有的對象都會經歷這幾個階段。
jQuery提供了三個層次的ajax方法,位於最底層的$.ajax()、第二層的$.load()、$.get()、$.post(),以及第三層的$.getScript()、$.getJson()。
先來說明第二層的方法。
1. $(‘selector’).load(url,data,function)方法
這個方法可以遠程加載HTML代碼並插入選中的DOM結點中。
其中data爲object類型。
無論ajax請求有沒有成功,請求完成後都會觸發回調函數,該函數有三個參數:responseText,textStatus(sucsess,error,notmodified,timeout中的一種),XMLHttpRequest。
如果只需加載html文檔中的部分元素,可在url後面傳入選擇器參數(第一個空格後的爲選擇器),指定要加載的部分:
$('#result').load('ajax/test.html #container');
· 1
調用方式爲:$ele.load(url,data,function)即可將響應的html片段寫入ele元素中。
回調函數會在HTML 已經被插入完時被調用,在每個匹配的元素上被調用一次,並且 this始終指向當前正在處理的 DOM 元素。
默認使用 GET 方式 , 如果data參數提供一個對象,那麼使用 POST 方式。
2.$.get(url,data,function,type)和$.post()
這兩個方法是全局函數,而非某個jQuery對象的函數。load方法常用於加載靜態數據文件,如果要向服務器傳遞參數可以用這兩個方法。
其中data爲object類型,type爲期待服務器返回的數據類型(html,xml等);回調函數只有請求成功即textStatus爲success時才調用。該函數包括兩個參數:data,textStatus。data爲返回的數據,可以爲xml文檔、json文件、html片段等。
例子:
<formid="form1"action="#">
<p>評論:</p>
<p>姓名: <inputtype="text"name="username"id="username" /></p>
<p>內容: <textareaname="content"id="content" rows="2"cols="20"></textarea></p>
<p><inputtype="button"id="send"value="提交"/></p>
</form>
<div class='comment'>已有評論:</div>
<divid="resText" >
</div>
//JS代碼爲
<script>
$(function(){
$("#send").click(function(){
$.get("get1.php",{username:$('#username').val(), content:$('#content').val()},
function(data){
$("#resText").html(data);
});
})
});
</script>
當返回數據爲XML文檔時,可以像解析html文檔一樣解析其中的元素,先用$(data)將返回文檔變成一個jQuery對象(data就相當於html DOM樹中的document結點),然後可以使用jQuery中的相關方法獲取到樹中結點的值,再構造成html格式的字符串然後通過html()方法寫入網頁中。
當返回數據問json文件時,data就是一個可被JavaScript直接使用的數據,如果是一個對象,可直接使用data.proptertyname獲取其中屬性值,如果data是數組,則可通過data[index]訪問其中的元素。
post方法與get結構相同,其區別有一下幾個:
get是將參數附着在url後傳遞,而post則是作爲請求的主體來傳送。用get傳遞的數據會被瀏覽器緩存起來,不太安全。
3. $.getScript(url,[callback])和$.getJson(url,[data],[callback])
$.getScript用來加載JavaScript文件(有時候沒有必要一次性加載完所有js文件,需要的時候再加載)。加載完後會自動執行。
回調函數會在成功加載js文件後執行。
$.getJson用於加載json文件,和$.getScript的函數結構一樣。補充一點就是回調函數的參數data是獲取到的Json文件對象。可使用全局方法$.each(data,function(index/key,ele/value))來遍歷集合data(可爲數組或對象)中的元素。
4. $ajax()
例子:
$("#save").click(function(){
$.ajax({
type:"POST",
url:"serverjson.php",
data:{ //傳送給服務器的數據
name:$("#staffName").val(),
number:$("#staffNumber").val(),
sex:$("#staffSex").val(),
job:$("#staffJob").val()
},
dataType:"json", //期望服務器發送會的數據格式
//請求成功的回調函數,data爲返回的數據
success:function(data){
if(data.success){
$("#createResult").html(data.msg);
}else{
$("#createResult").html("出現錯誤:"+data.msg);
}
},
//請求失敗的回調函數,參數爲XHR對象
error:function(jqXHR){
alert("發生錯誤:"+jqXHR.status);
}
})
})
所有jQuery的Ajax方法都返回一個XMLHTTPRequest對象的超集
附:jquery中的ajax方法參數
1.url:
要求爲String類型的參數,(默認爲當前頁地址)發送請求的地址。
2.type:
要求爲String類型的參數,請求方式(post或get)默認爲get。注意其他http請求方法,例如put和delete也可以使用,但僅部分瀏覽器支持。
3.timeout:
要求爲Number類型的參數,設置請求超時時間(毫秒)。此設置將覆蓋$.ajaxSetup()方法的全局設置。
4.async:
要求爲Boolean類型的參數,默認設置爲true,所有請求均爲異步請求。如果需要發送同步請求,請將此選項設置爲false。注意,同步請求將鎖住瀏覽器,用戶其他操作必須等待請求完成纔可以執行。
5.cache:
要求爲Boolean類型的參數,默認爲true(當dataType爲script時,默認爲false),設置爲false將不會從瀏覽器緩存中加載請求信息。
6.data:
要求爲Object或String類型的參數,發送到服務器的數據。如果已經不是字符串,將自動轉換爲字符串格式。get請求中將附加在url後。防止這種自動轉換,可以查看 processData選項。對象必須爲key/value格式,例如{foo1:"bar1",foo2:"bar2"}轉換爲&foo1=bar1&foo2=bar2。如果是數組,JQuery將自動爲不同值對應同一個名稱。例如{foo:["bar1","bar2"]}轉換爲&foo=bar1&foo=bar2。
7.dataType:
上送到服務器時的數據類型可選項:
Text,
Json
例子:data:{name:”admin”,password:”123456”}
datatype:json
正常是要加上datatype:json
如果沒有申明數據類型,需要轉換
JSON.stringsty()
要求爲String類型的參數,預期服務器返回的數據類型。如果不指定,JQuery將自動根據http包mime信息返回responseXML或responseText,並作爲回調函數參數傳遞。可用的類型如下:
xml:返回XML文檔,可用JQuery處理。
html:返回純文本HTML信息;包含的script標籤會在插入DOM時執行。
script:返回純文本JavaScript代碼。不會自動緩存結果。除非設置了cache參數。注意在遠程請求時(不在同一個域下),所有post請求都將轉爲get請求。
json:返回JSON數據。
jsonp:JSONP格式。使用SONP形式調用函數時,例如myurl?callback=?,JQuery將自動替換後一個“?”爲正確的函數名,以執行回調函數。
text:返回純文本字符串。
8.beforeSend:
要求爲Function類型的參數,發送請求前可以修改XMLHttpRequest對象的函數,例如添加自定義HTTP頭。在beforeSend中如果返回false可以取消本次ajax請求。XMLHttpRequest對象是惟一的參數。
function(XMLHttpRequest){
this; //調用本次ajax請求時傳遞的options參數
}
9.complete:
要求爲Function類型的參數,請求完成後調用的回調函數(請求成功或失敗時均調用)。參數:XMLHttpRequest對象和一個描述成功請求類型的字符串。
function(XMLHttpRequest,textStatus){
this; //調用本次ajax請求時傳遞的options參數
}
10.success:要求爲Function類型的參數,請求成功後調用的回調函數,有兩個參數。
(1)由服務器返回,並根據dataType參數進行處理後的數據。
(2)描述狀態的字符串。
function(data, textStatus){
//data可能是xmlDoc、jsonObj、html、text等等
this; //調用本次ajax請求時傳遞的options參數
}
11.error:
要求爲Function類型的參數,請求失敗時被調用的函數。該函數有3個參數,即XMLHttpRequest對象、錯誤信息、捕獲的錯誤對象(可選)。ajax事件函數如下:
function(XMLHttpRequest, textStatus,errorThrown){
//通常情況下textStatus和errorThrown只有其中一個包含信息
this; //調用本次ajax請求時傳遞的options參數
}
12.contentType:
要求爲String類型的參數,當發送信息至服務器時,內容編碼類型默認爲"application/x-www-form-urlencoded"。該默認值適合大多數應用場合。
13.dataFilter:
要求爲Function類型的參數,給Ajax返回的原始數據進行預處理的函數。提供data和type兩個參數。data是Ajax返回的原始數據,type是調用jQuery.ajax時提供的dataType參數。函數返回的值將由jQuery進一步處理。
function(data, type){
//返回處理後的數據
return data;
}
14.dataFilter:
要求爲Function類型的參數,給Ajax返回的原始數據進行預處理的函數。提供data和type兩個參數。data是Ajax返回的原始數據,type是調用jQuery.ajax時提供的dataType參數。函數返回的值將由jQuery進一步處理。
function(data, type){
//返回處理後的數據
return data;
}
15.global:
要求爲Boolean類型的參數,默認爲true。表示是否觸發全局ajax事件。設置爲false將不會觸發全局ajax事件,ajaxStart或ajaxStop可用於控制各種ajax事件。
16.ifModified:
要求爲Boolean類型的參數,默認爲false。僅在服務器數據改變時獲取新數據。服務器數據改變判斷的依據是Last-Modified頭信息。默認值是false,即忽略頭信息。
17.jsonp:
要求爲String類型的參數,在一個jsonp請求中重寫回調函數的名字。該值用來替代在"callback=?"這種GET或POST請求中URL參數裏的"callback"部分,例如{jsonp:'onJsonPLoad'}會導致將"onJsonPLoad=?"傳給服務器。
18.username:
要求爲String類型的參數,用於響應HTTP訪問認證請求的用戶名。
19.password:
要求爲String類型的參數,用於響應HTTP訪問認證請求的密碼。
20.processData:
要求爲Boolean類型的參數,默認爲true。默認情況下,發送的數據將被轉換爲對象(從技術角度來講並非字符串)以配合默認內容類型"application/x-www-form-urlencoded"。如果要發送DOM樹信息或者其他不希望轉換的信息,請設置爲false。
21.scriptCharset:
要求爲String類型的參數,只有當請求時dataType爲"jsonp"或者"script",並且type是GET時纔會用於強制修改字符集(charset)。通常在本地和遠程的內容編碼不同時使用。