### 1. 摘要
本系列文章將帶您進入jQuery的精彩世界, 其中有很多作者具體的使用經驗和解決方案, 即使你會使用jQuery也能在閱讀中發現些許秘籍.
本篇文章講解如何使用jQuery方便快捷的實現Ajax功能.統一所有開發人員使用Ajax的方式.
### 2. 前言
Ajax讓用戶頁面豐富起來, 增強了用戶體驗. 使用Ajax是所有Web開發的必修課. 雖然Ajax技術并不復雜, 但是實現方式還是會因為每個開發人員的而有所差異.jQuery提供了一系列Ajax函數來幫助我們統一這種差異, 并且讓調用Ajax更加簡單.
### 3. 原始Ajax與jQuery中的Ajax
首先通過實例, 來看一下jQuery實現Ajax有多簡單. 下面是一個使用原始Ajax的示例:
~~~
<html>
<head>
<title>jQuery Ajax</title>
<script type="text/javascript">
$(function()
{
var xhr = new AjaxXmlHttpRequest();
$("#btnAjaxOld").click(function(event)
{
var xhr = new AjaxXmlHttpRequest();
xhr.onreadystatechange = function()
{
if (xhr.readyState == 4)
{
document.getElementById("divResult").innerHTML = xhr.responseText;
}
}
xhr.open("GET", "data/AjaxGetCityInfo.aspx?resultType=html", true);
xhr.send(null);
});
})
//跨瀏覽器獲取XmlHttpRequest對象
function AjaxXmlHttpRequest()
{
var xmlHttp;
try
{
// Firefox, Opera 8.0+, Safari
xmlHttp = new XMLHttpRequest();
}
catch (e)
{
// Internet Explorer
try
{
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try
{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e)
{
alert("您的瀏覽器不支持AJAX!");
return false;
}
}
}
return xmlHttp;
}
</script>
</head>
<body>
<button id="btnAjaxOld">原始Ajax調用</button><br />
<br />
<div id="divResult"></div>
</body>
</html>
~~~
上面的實例中, `data/AjaxGetCityInfo.aspx?resultType=html` 地址會返回一段HTML代碼.
使用原始Ajax, 我們需要做較多的事情, 比如創建XmlHttpRequest對象, 判斷請求狀態, 編寫回調函數等.
而用jQuery的Load方法, 只需要一句話:
~~~
$("#divResult").load("data/AjaxGetCityInfo.aspx", { "resultType": "html" });
~~~
曾經我是一個原始Ajax的絕對擁護者, 甚至摒棄微軟的Asp.net Ajax, 因為我想要最高的代碼靈活度. 使用原始Ajax讓我感覺完成自己的工作更加輕松, 即使多寫了一些代碼. 但是當我去翻看別人的Ajax代碼并且嘗試修改的時候, 我改變了我的看法——我們的代碼到處分布著創建XmlHttpRequest方法的函數, 或者某些Ajax程序邏輯性和結構性很差, 很難看懂.
我們可以將通用方法放到一個js文件中, 然后告訴大家”嘿伙伴們, 都來用這個js中的方法”. 但是在某些時候有些新來的外包人員并不知道有這個js文件的存在. 而且其實這個通用的js就是一個公共的腳本類庫, 我相信沒有人會覺得自己開發一個類庫會比jQuery更好!
所以我放棄了制造輪子的計劃, 大家都使用jQuery編寫Ajax相關的方法就可以解決各種差異性問題, 并且讓工作更有效率.
現在只是用jQuery的Ajax函數, 我的頁面變得簡潔了:
~~~
<html>
<head>
<title>jQuery Ajax</title>
<script type="text/javascript" src="scripts/jquery-1.3.2-vsdoc2.js"></script>
<script type="text/javascript">
$(function()
{
$("#btnGetHtml").click(function(event)
{
$("#divResult").load("data/AjaxGetCityInfo.aspx", { "resultType": "html" });
});
})
</script>
</head>
<body>
<button id="btnAjaxJquery">使用jQuery的load方法</button>
<br />
<div id="divResult"></div>
</body>
</html>
~~~
### 4. jQuery Ajax詳解
jQuery提供了幾個用于發送Ajax請求的函數. 其中最核心也是最復雜的是`jQuery.ajax( options )`,所有的其他Ajax函數都是它的一個簡化調用. 當我們想要完全控制Ajax時可以使用此結果, 否則還是使用簡化方法如get, post, load等更加方便. 所以jQuery.ajax( options ) 方法放到最后一個介紹. 先來介紹最簡單的load方法:
**1. load( url, [data], [callback] )**
~~~
Returns: jQuery包裝集
~~~
說明:
- load方法能夠載入遠程 HTML 文件代碼并插入至 DOM 中。
- 默認使用 GET 方式, 如果傳遞了data參數則使用Post方式.
- 傳遞附加參數時自動轉換為 POST 方式。jQuery 1.2 中,可以指定選擇符,來篩選載入的 HTML 文檔,DOM 中將僅插入篩選出的 HTML 代碼。語法形如 “url #some > selector”, 默認的選擇器是”body>*”.
講解:
- load是最簡單的Ajax函數, 但是使用具有局限性:
- 它主要用于直接返回HTML的Ajax接口
- load是一個jQuery包裝集方法,需要在jQuery包裝集上調用,并且會將返回的HTML加載到對象中, 即使設置了回調函數也還是會加載.
不過不可否認load接口設計巧妙并且使用簡單.下面通過示例來演示Load接口的使用:
~~~
<html>
<head>
<title>jQuery Ajax - Load</title>
<script type="text/javascript" src="../scripts/jquery-1.3.2-vsdoc2.js"></script>
<script type="text/javascript">
$(function()
{
$("#btnAjaxGet").click(function(event)
{
//發送Get請求
$("#divResult").load("../data/AjaxGetMethod.aspx?param=btnAjaxGet_click" + "&tim
estamp=" + (new Date()).getTime());
});
$("#btnAjaxPost").click(function(event)
{
//發送Post請求
$("#divResult").load("../data/AjaxGetMethod.aspx", { "param": "btnAjaxPost_click" });
});
$("#btnAjaxCallBack").click(function(event)
{
//發送Post請求, 返回后執行回調函數.
$("#divResult").load("../data/AjaxGetMethod.aspx", { "param": "btnAjaxCallBack_click
" }, function(responseText, textStatus, XMLHttpRequest)
{
responseText = " Add in the CallBack Function! <br/>" + responseText
$("#divResult").html(responseText); //或者: $(this).html(responseText);
});
});
$("#btnAjaxFiltHtml").click(function(event)
{
//發送Get請求, 從結果中過濾掉 "鞍山" 這一項
$("#divResult").load("../data/AjaxGetCityInfo.aspx?resultType=html" + "×tamp
=" + (new Date()).getTime() + " ul>li:not(:contains('鞍山'))");
});
})
</script>
</head>
<body>
<button id="btnAjaxGet">使用Load執行Get請求</button><br />
<button id="btnAjaxPost">使用Load執行Post請求</button><br />
<button id="btnAjaxCallBack">使用帶有回調函數的Load方法</button><br />
<button id="btnAjaxFiltHtml">使用selector過濾返回的HTML內容</button>
<br />
<div id="divResult"></div>
</body>
</html>
~~~
上面的示例演示了如何使用Load方法.
提示:
- 我們要時刻注意瀏覽器緩存, 當使用GET方式時要添加時間戳參數 (net Date()).getTime() 來保證每次發送的URL不同, 可以避免瀏覽器緩存.
- 當在url參數后面添加了一個空格, 比如” “的時候, 會出現”無法識別符號”的錯誤, 請求還是能正常發送. 但是無法加載HTML到DOM. 刪除后問題解決.
**2.jQuery.get( url, [data], [callback], [type] )**
~~~
Returns: XMLHttpRequest
~~~
說明:
- 通過遠程 HTTP GET 請求載入信息。
- 這是一個簡單的 GET 請求功能以取代復雜 `$.ajax` 。請求成功時可調用回調函數。如果需要在出錯時執行函數,請使用 `$.ajax`。
講解:
- 此函數發送Get請求, 參數可以直接在url中拼接, 比如:
~~~
$.get("../data/AjaxGetMethod.aspx?param=btnAjaxGet_click");
~~~
或者通過data參數傳遞:
~~~
$.get("../data/AjaxGetMethod.aspx", { "param": "btnAjaxGet2_click" });
~~~
- 兩種方式效果相同, data參數會自動添加到請求的url中,如果url中的某個參數, 又通過data參數傳遞, 不會自動合并相同名稱的參數.
回調函數的簽名如下:
~~~
function (data, textStatus) {
// data could be xmlDoc, jsonObj, html, text, etc
this; // the options for this ajax request
}
~~~
其中data是返回的數據, testStatus表示狀態碼, 可能是如下值:在回調函數中的this是獲取options對象的引用
type參數是指data數據的類型, 可能是下面的值:
**“xml”, “html”, “script”, “json”, “jsonp”, “text”.默認為”html”.**
jQuery.getJSON( url, [data], [callback] ) 方法就相當于 jQuery.get(url, [data],[callback], “json”)
**3. jQuery.getJSON( url, [data], [callback] )**
~~~
Returns: XMLHttpRequest
~~~
相當于: jQuery.get(url, [data],[callback], “json”)
說明:
- 通過 HTTP GET 請求載入 JSON 數據。
- 在 jQuery 1.2 中,您可以通過使用JSONP 形式的回調函數來加載其他網域的JSON數據,如 “myurl?callback=?”。jQuery 將自動替換 ? 為正確的函數名,以執行回調函數。
注意:此行以后的代碼將在這個回調函數執行前執行。
講解:
- getJSON函數僅僅將get函數的type參數設置為”JSON”而已. 在回調函數中獲取的數據已經是按照JSON格式解析后的對象了:
~~~
$.getJSON("../data/AjaxGetCityInfo.aspx", { "resultType": "json" }, function(data, textStatus)
{
alert(data.length);
alert(data[0].CityName);
});
~~~
服務器端返回的字符串如下:
~~~
[{""pkid"":""0997"",""ProvinceId"":""XJ"",""CityName"":""阿克蘇"",""CityNameEn"":""Akesu"",""PostCode"":""843000"",""isHotCity"":false},
{""pkid"":""0412"",""ProvinceId"":""LN"",""CityName"":""鞍山"",""CityNameEn"":""Anshan"",""PostCode"":""114000"",""isHotCity"":false}]
~~~
示例中我返回的餓是一個數組, 使用data.length可以獲取數組的元素個數, data[0]訪問第一個元素, data[0].CityName訪問第一個元素的CityName屬性.
**4. jQuery.getScript( url, [callback] )**
~~~
Returns: XMLHttpRequest
~~~
相當于: jQuery.get(url, null, [callback], “script”)
說明:
- 通過 HTTP GET 請求載入并執行一個 JavaScript 文件。
- jQuery 1.2 版本之前,getScript 只能調用同域 JS 文件。 1.2中,您可以跨域調用 JavaScript 文件。
講解:
以前我使用dojo類庫時官方默認的文件不支持跨域最后導致我放棄使用dojo(雖然在網上找到了可以跨域的版本, 但是感覺不夠完美). 所以我特別對這個函數的核心實現和使用做了研究.
首先了解此函數的jQuery內部實現, 仍然使用get函數, jQuery所有的Ajax函數包括get最后都是用的是jQuery.ajax(), getScript將傳入值為”script”的type參數, 最后在Ajax函數中對type為script的請求做了如下處理:
~~~
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.src = s.url;
~~~
上面的代碼動態建立了一個script語句塊, 并且將其加入到head中:
~~~
head.appendChild(script);
~~~
當腳本加載完畢后, 再從head中刪除:
~~~
// Handle Script loading
if ( !jsonp ) {
var done = false;
// Attach handlers for all browsers
script.onload = script.onreadystatechange = function(){
if ( !done && (!this.readyState ||
this.readyState == "loaded" || this.readyState == "complete") ) {
done = true;
success();
complete();
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
head.removeChild( script );
}
};
}
~~~
我主要測試了此函數的跨域訪問和多瀏覽器支持.下面是結果:

下面是我關鍵的測試語句, 也用來演示如何使用getScript函數:
~~~
$("#btnAjaxGetJSON").click(function(event)
{
$.getScript("../scripts/getScript.js", function(data, textStatus)
{
alert(data);
alert(textStatus);
alert(this.url);
});
});
$("#btnAjaxGetJSONXSS").click(function(event)
{
$.getScript("http://resource.elong.com/getScript.js", function(data, textStatus)
{
alert(data);
alert(textStatus);
alert(this.url);
});
});
~~~
**5. jQuery.post( url, [data], [callback], [type] )**
~~~
Returns: XMLHttpRequest
~~~
說明:
- 通過遠程 HTTP POST 請求載入信息。
- 這是一個簡單的 POST 請求功能以取代復雜 `$.ajax` 。請求成功時可調用回調函數。如果需要在出錯時執行函數,請使用 `$.ajax`。
講解:
- 具體用法和get相同, 只是提交方式由”GET”改為”POST”.
**6. jQuery.ajax( options )**
~~~
Returns: XMLHttpRequest
~~~
說明:
- 通過 HTTP 請求加載遠程數據。
- jQuery 底層 AJAX 實現。簡單易用的高層實現見 `$.get, $.post` 等。
- `$.ajax()` 返回其創建的 XMLHttpRequest 對象。大多數情況下你無需直接操作該對象,但特殊情況下可用于手動終止請求。
- `$.ajax()` 只有一個參數:參數 key/value 對象,包含各配置及回調函數信息。
jQuery 1.2 中,您可以跨域加載 JSON 數據,使用時需將數據類型設置為 JSONP。使用 JSONP 形式調用函數時,如 “myurl?callback=?” jQuery 將自動替換 ? 為正確的函數名,以執行回調函數。數據類型設置為 “jsonp” 時,jQuery 將自動調用回調函數。
### 5、Ajax相關函數.
jQuery提供了一些相關函數能夠輔助Ajax函數.
**1. jQuery.ajaxSetup( options )**
無返回值
說明:
- 設置全局 AJAX 默認options選項。
講解:
有時我們的希望設置頁面上所有Ajax屬性的默認行為.那么就可以使用此函數設置options選項, 此后所有的Ajax請求的默認options將被更改.
比如,設置 AJAX 請求默認地址為 “/xmlhttp/”,禁止觸發全局 AJAX 事件,用 POST 代替默認 GET 方法。其后的 AJAX 請求不再設置任何選項參數:
~~~
$.ajaxSetup({
url: "/xmlhttp/",
global: false,
type: "POST"
});
$.ajax({ data: myData });
~~~
**2. serialize( )**
~~~
Returns: String
~~~
說明:
- 序列表表格內容為字符串,用于 Ajax 請求。
- 序列化最常用在將表單數據發送到服務器端時. 被序列化后的數據是標準格式, 可以被幾乎所有的而服務器端支持.
- 為了盡可能正常工作, 要求被序列化的表單字段都有name屬性, 只有一個eid是無法工作的.
像這樣寫name屬性:
~~~
<input id="email" name="email" type="text" />
~~~
講解:
serialize()函數將要發送給服務器的form中的表單對象拼接成一個字符串. 便于我們使用Ajax發送時獲取表單數據. 這和一個From按照Get方式提交時, 自動將表單對象的名/值放到url上提交差不多.
比如這樣一個表單:

生成的字符串為:single=Single¶m=Multiple¶m=Multiple3&check=check2&radio=radio1
**3. serializeArray( )**
~~~
Returns: Array<Object>
~~~
說明:
- 序列化表格元素 (類似 ‘.serialize()’ 方法) 返回 JSON 數據結構數據。
- 注意,此方法返回的是JSON對象而非JSON字符串。需要使用插件或者第三方庫進行字符串化操作。
講解:
看說明文檔讓我有所失望, 使用此函數獲取到的是JSON對象, 但是jQuery中沒有提供將JSON對象轉化為JSON字符串的方法.
在JSON官網上沒有找到合適的JSON編譯器, 最后選用了jquery.json這個jQuery插件:
[http://code.google.com/p/jquery-json/](http://code.google.com/p/jquery-json/)
使用起來異常簡單:
~~~
var thing = {plugin: 'jquery-json', version: 1.3};
var encoded = $.toJSON(thing); //'{"plugin": "jquery-json", "version": 1.3}'
var name = $.evalJSON(encoded).plugin; //"jquery-json"
var version = $.evalJSON(encoded).version; // 1.3
~~~
使用serializeArray( ) 再配合 `$.toJSON` 方法, 我們可以很方便的獲取表單對象的JSON, 并且轉換為JSON字符串:
~~~
$("#results").html( $.toJSON( $("form").serializeArray() ));
~~~
結果為:
~~~
[{"name": "single", "value": "Single"}, {"name": "param", "value": "Multiple"}, {"name": "param"
, "value": "Multiple3"}, {"name": "check", "value": "check2"}, {"name": "radio", "value": "radio1"}]
~~~
### 6、全局Ajax事件
在jQuery.ajaxSetup( options ) 中的options參數屬性中, 有一個global屬性:global 值類型:布爾值, 默認值: true,
說明:
是否觸發全局的Ajax事件.
這個屬性用來設置是否觸發全局的Ajax事件. 全局Ajax事件是一系列伴隨Ajax請求發生的事件.主要有如下事件:
| 第一列 | 第二列 |
|-----|-----|
| ajaxComplete( callback ) | AJAX 請求完成時執行函數 |
| ajaxError( callback ) | AJAX 請求發生錯誤時執行函數 |
| ajaxSend( callback ) | AJAX請求發送前執行函數 |
| ajaxStart( callback ) | AJAX請求開始時執行函數 |
| ajaxStop( callback ) | AJAX請求結束時執行函數 |
| ajaxSuccess( callback ) | AJAX 請求成功時執行函數 |
用一個示例講解各個事件的觸發順序:
~~~
<html >
<head>
<title>jQuery Ajax - AjaxEvent</title>
<script type="text/javascript" src="../scripts/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
$("#btnAjax").bind("click", function(event)
{
$.get("../data/AjaxGetMethod.aspx");
})
$("#divResult").ajaxComplete(function(evt, request, settings) { $(this).append('<div>
ajaxComplete</div>'); })
$("#divResult").ajaxError(function(evt, request, settings) { $(this).append('<div>
ajaxError</div>'); })
$("#divResult").ajaxSend(function(evt, request, settings) { $(this).append('<div>
ajaxSend</div>'); })
$("#divResult").ajaxStart(function() { $(this).append('<div>ajaxStart</div>'); })
$("#divResult").ajaxStop(function() { $(this).append('<div>ajaxStop</div>'); })
$("#divResult").ajaxSuccess(function(evt, request, settings) { $(this).append('<div>
ajaxSuccess</div>'); })
});
</script>
</head>
<body>
<br /><button id="btnAjax">發送Ajax請求</button><br/>
<div id="divResult"></div>
</body>
</html>
~~~
結果如圖:

我們可以通過將默認options的global屬性設置為false來取消全局Ajax事件的觸發.
### 7. 注意事項
1. 如果在Get請求發送的url中有兩個同名參數, 比如兩個param參數:
[http://localhost/AjaxGetMethod.aspx?param=Multiple¶m=Multiple3](http://localhost/AjaxGetMethod.aspx?param=Multiple¶m=Multiple3)
使用服務器端方法獲取param參數:
~~~
if (!String.IsNullOrEmpty(HttpContext.Current.Request["Param"]))
{
param = HttpContext.Current.Request["Param"];
}
~~~
此時獲取到得param是一個用”,”分隔多個值的字符串:
Multiple,Multiple3
### 8. 總結
本文介紹如何使用jquery實現Ajax功能. 用于發送Ajax請求的相關函數如load, get, getJSON和post這些漸變Ajax方法, 對于核心的ajax 方法沒有過多介紹, 主要是通過配置復雜的參數實現完全控制Ajax請求. 另外講解了ajax的輔助函數比如用于序列化表單對象為字符串的serialize()方法, 用于將表單對象序列化為JSON對象的serializeArray()方法. 這些在使用腳本獲取數據實現與服務器端交互是很有用, JSON格式的數據在處理大對象編程時將我們從混亂的屬性字符串中解放出來.
jQuery還提供錄入全局ajax事件這一個特殊的事件, 并且可以在一個對象上設置這些事件, 在發送Ajax請求的各個生命周期上會調用這些事件, 可以通過修改默認的options對象的global屬性打開或關閉全局事件.