借助于 XMLHttpRequest,瀏覽器可以在整個(gè)頁(yè)面不刷新的情況下與服務(wù)端進(jìn)行交互,這就是所謂的 Ajax(Asynchronous JavaScript and XML)。Ajax 可以為用戶提供更為豐富的用戶體驗(yàn)。
Ajax 請(qǐng)求由 JavaScript 驅(qū)動(dòng),通過(guò) JavaScript 代碼向 URL 發(fā)送一個(gè)請(qǐng)求,待服務(wù)端有響應(yīng)時(shí)會(huì)觸發(fā)一個(gè)回調(diào)函數(shù),可以在這里回調(diào)函數(shù)里面處理服務(wù)端返回的信息。由于整個(gè)發(fā)送請(qǐng)求和響應(yīng)的過(guò)程是異步的,所以在此期間頁(yè)面中其它 Javascript 代碼仍然繼續(xù)執(zhí)行,不會(huì)中斷。
jQuery 對(duì) Ajax 當(dāng)然也提供了很好的支持,而且還抽象了各種瀏覽器對(duì)于 Ajax 支持方面另人痛苦的差異。它不但提供了全功能的 $.ajax() 方法,還有諸如 $.get(),$.getScript(),$.getJSON(),$.post() 和 $().load() 等更為簡(jiǎn)便的方法。
盡管被命名為 Ajax,但是很多 Ajax 應(yīng)用并沒(méi)有使用 XML,特別是 jQuery 方面的 Ajax 應(yīng)用,大多數(shù)都沒(méi)有使用 XML;反而用得比較多的情況是:純文本、HTML 以及 JSON(JavaScript Object Notation)。
一般情況下,由于同源策略(同協(xié)議,同域名,同端口)的限制,Ajax 并不能跨域執(zhí)行請(qǐng)求,除非使用諸如 JSONP(JSON with Padding) 之類的方案,才能實(shí)現(xiàn)一些受限的跨域功能。
關(guān)于 Ajax 的一些重要概念
GET vs POST,這是兩種最常用的向服務(wù)端發(fā)送請(qǐng)求的方法,正確理解這兩種方法的區(qū)別對(duì)于 Ajax 開(kāi)發(fā)非常重要。
GET 方法通常用于執(zhí)行一些非破壞性的操作(就是說(shuō),只從服務(wù)端獲取信息,不修改服務(wù)端上的信息)。例如,搜索查詢服務(wù)一般會(huì)使用 GET 請(qǐng)求。另外,GET 請(qǐng)求還可能會(huì)被瀏覽器緩存,這可能會(huì)導(dǎo)致一些不可預(yù)知的問(wèn)題。一般情況下 GET 請(qǐng)求只能通過(guò)查詢字符串的方式向服務(wù)端發(fā)送數(shù)據(jù)。
POST 方法通常用于在服務(wù)端上執(zhí)行一些破壞性的操作(就是說(shuō),會(huì)修改服務(wù)端上的數(shù)據(jù))。例如,當(dāng)你發(fā)表一篇博客的時(shí)候,用的應(yīng)該就是 POST 請(qǐng)求。和 GET 請(qǐng)求不一樣,POST 請(qǐng)求不存在緩存問(wèn)題。POST 請(qǐng)求中,查詢字符串作為 URL 的一部分也能向服務(wù)端提交數(shù)據(jù),但不推薦這種方法,所有數(shù)據(jù)應(yīng)該跟 URL 分開(kāi)單獨(dú)發(fā)送。
數(shù)據(jù)類型,jQuery 通常要求指明服務(wù)端返回的數(shù)據(jù)類型,某些情況寫數(shù)據(jù)類型可能已經(jīng)包含在方法名稱中了,如 $.getJSON(),除此之外,它都會(huì)被作為一個(gè)可配置的對(duì)象的一部分,該對(duì)象最終會(huì)作為 $.ajax() 方法的參數(shù)。數(shù)據(jù)類型通常有以下幾種:
異步執(zhí)行,Ajax 中的 A 指的是異步(Asynchronous)。說(shuō)到這里可能很多 jQuery 初學(xué)者一下子很難理解什么叫異步,因?yàn)槟J(rèn)情況下 Ajax 請(qǐng)求就是異步的,服務(wù)端返回的信息并非馬上就能獲取到。所有服務(wù)端返回的信息只能在一個(gè)回調(diào)函數(shù)中處理。例如以下這段代碼,是錯(cuò)誤的:
var response;$.get('foo.php', function(r) { response = r; });console.log(response); // undefined!
正確的做法應(yīng)該是在回調(diào)函數(shù)中處理服務(wù)端返回的數(shù)據(jù),回調(diào)函數(shù)在 Ajax 請(qǐng)求成功完成時(shí)才被執(zhí)行,這個(gè)時(shí)候才能獲取到來(lái)自服務(wù)端的數(shù)據(jù):
$.get('foo.php', function(response) { console.log(response); });
同源策略及 JSONP,前面已經(jīng)說(shuō)過(guò),一般情況下 Ajax 的請(qǐng)求會(huì)被限制在相同協(xié)議(http 或 https)、相同端口、相同域名下才能正確執(zhí)行,但是 HTML 的 <script> 標(biāo)簽卻無(wú)此限制,它可以載入任何域下的腳本,jQuery 正是利用了這一點(diǎn)才得以擁有跨域執(zhí)行 Ajax 的能力。
所謂 JSONP,就是其它域的服務(wù)端返回給我們的是 JavaScript 代碼,這段代碼可以被加載到 HTML 中的 <script> 標(biāo)簽中,這段 JavaScript 代碼中包含有從其它域下的服務(wù)端返回的 JSON 數(shù)據(jù),并以回調(diào)函數(shù)的形式提供。這樣一來(lái) jQuery 就回避了同源策略的限制,曲線擁有了跨域執(zhí)行 Ajax 的能力。
Ajax 調(diào)試工具,現(xiàn)在比較新的瀏覽器如 Chrome 和 Safari,甚至 IE 都內(nèi)置了調(diào)試工具,F(xiàn)irefox 也有無(wú)比強(qiáng)大 FireBug 插件,借助于這些調(diào)試工具,可以非常詳細(xì)的查看 Ajax 的執(zhí)行過(guò)程。
和 Ajax 相關(guān)的一些方法
jQuery 提供了好多種簡(jiǎn)便的 Ajax 方法,但是它們的核心都是 $.ajax,所以必須正確理解 $.ajax。
jQuery 的 $.ajax 是創(chuàng)建 Ajax 請(qǐng)求中最直接也是最有效的方法,它的參數(shù)是一個(gè) JavaScript 對(duì)象,我們可以在這個(gè)對(duì)象中對(duì) Ajax 作非常詳細(xì)的配置。另外,$.ajax 方法還可以分別定義 Ajax 請(qǐng)求成功和失敗時(shí)的回調(diào)函數(shù);而且它以一個(gè)可配置的對(duì)象作為參數(shù)的特性,使得我們可以在 Ajax 方法外配置這個(gè)對(duì)象,然后再傳進(jìn)來(lái),這非常有助于實(shí)現(xiàn)代碼復(fù)用。關(guān)于這個(gè)方法的詳細(xì)文檔:http://api.jquery.com/jQuery.ajax/
一個(gè)典型的示例如下:
$.ajax({ // 要請(qǐng)求的 URL url : 'post.php', // 要發(fā)給服務(wù)端的數(shù)據(jù) // (將會(huì)轉(zhuǎn)化為查詢字符串,如:?id=123) data : { id : 123 }, // 定義此 Ajax 請(qǐng)求是 POST 還是 GET type : 'GET', // 服務(wù)端返回的數(shù)據(jù)類型 dataType : 'json', // Ajax 成功執(zhí)行時(shí)的回調(diào)函數(shù); // 回調(diào)函數(shù)的參數(shù)即為服務(wù)端返回的數(shù)據(jù) success : function(json) { $('<h1/>').text(json.title).appendTo('body'); $('<div class="content"/>') .html(json.html).appendTo('body'); }, // 如果 Ajax 執(zhí)行失敗; // 將返回原始錯(cuò)誤信息以及狀態(tài)碼 // 傳入這個(gè)回調(diào)函數(shù)中 error : function(xhr, status) { alert('Sorry, there was a problem!'); }, // 這里是無(wú)論 Ajax 是否成功執(zhí)行都會(huì)觸發(fā)的回調(diào)函數(shù) complete : function(xhr, status) { alert('The request is complete!'); }});
備注:
關(guān)于 dataType :如果這里定義的 dataType 跟服務(wù)端返回的數(shù)據(jù)格式不一樣,我們的代碼就可能會(huì)執(zhí)行失敗,并且很難查出原因,因?yàn)?HTTP 返回的狀態(tài)碼并沒(méi)有顯示出錯(cuò)。所以在執(zhí)行 Ajax 請(qǐng)求的時(shí)候,一定要確保服務(wù)端返回的數(shù)據(jù)格式跟事先定義定義的一致。通常情況下驗(yàn)證 HTTP 頭信息中的 Content-type 是行之有效的辦法,對(duì)于 JSON 而言,對(duì)應(yīng)的 Content-type 應(yīng)該是 application/json。
$.ajax 的一些自定義選項(xiàng)
$.ajax 方法的自定義選項(xiàng)非常多,這也是此方法功能強(qiáng)大的原因所在。若要查閱所有自定義選項(xiàng),可參考官方文檔:http://api.jquery.com/jQuery.ajax/,下面只列出一些常用的選項(xiàng):
async :默認(rèn)值是 true,如果需要 Ajax 的執(zhí)行方式為同步,可將其設(shè)為 false。請(qǐng)注意,如果把這個(gè)值設(shè)為 false 了,那么你的其它 JavaScript 代碼將會(huì)被中斷執(zhí)行,直到此次 Ajax 請(qǐng)求完畢,接受到服務(wù)端返回的數(shù)據(jù)為止才會(huì)恢復(fù)。所以,請(qǐng)慎用此選項(xiàng)。
cache :設(shè)定是否緩存服務(wù)端發(fā)回的數(shù)據(jù)。對(duì)于 “script” 和 “jsonp” 之外的其它格式的數(shù)據(jù)而言,默認(rèn)值是 true。如果被設(shè)置為 false,向服務(wù)器發(fā)送請(qǐng)求的時(shí)候,URL 中會(huì)被加入一個(gè)查詢字符串,字符串的值是當(dāng)前的時(shí)間戳,以確保每次請(qǐng)求的 URL 都是不同的,當(dāng)然也就不存在緩存問(wèn)題了。JavaScript 中獲取時(shí)間戳的方法為 new Date().getTime()。
complete :Ajax 請(qǐng)求執(zhí)行完成時(shí)觸發(fā)的回調(diào)函數(shù),無(wú)論此次執(zhí)行成功與否,該回調(diào)函數(shù)都會(huì)被觸發(fā)。該回調(diào)函數(shù)可以接受服務(wù)端返回的原始信息及狀態(tài)碼。
context :定義回調(diào)函數(shù)執(zhí)行時(shí)的作用域(回調(diào)函數(shù) function(s) {alert(this)} 中的 this 指向誰(shuí)?)。默認(rèn)情況下,回調(diào)函數(shù)中的 this 指向傳遞給 $.ajax 方法的參數(shù),也就是那個(gè)大對(duì)象。
data :要發(fā)送給服務(wù)端的數(shù)據(jù),其值可以是一個(gè)對(duì)象或者查詢字符串,如 foo=bar&baz=bim。
dataType :服務(wù)端返回?cái)?shù)據(jù)的類型。如果不設(shè)置這個(gè)選項(xiàng),jQuery 會(huì)根據(jù)服務(wù)端返回?cái)?shù)據(jù)的 MIME 類型自行判斷。
error :當(dāng) Ajax 執(zhí)行錯(cuò)誤時(shí)將會(huì)觸發(fā)的回調(diào)函數(shù),該函數(shù)接受原始的請(qǐng)求信息及狀態(tài)碼。
jsonp :執(zhí)行 JSONP 請(qǐng)求時(shí)需要制定的回調(diào)函數(shù)名稱,默認(rèn)值是“callback”。
success :Ajax 成功執(zhí)行時(shí)將會(huì)觸發(fā)的回調(diào)函數(shù)。在函數(shù)中可獲取服務(wù)端返回的信息(如果 dataType 被設(shè)置成 JSON,返回的數(shù)據(jù)應(yīng)該是一個(gè) JavaScript 對(duì)象),當(dāng)然也可獲取服務(wù)端返回的原始數(shù)據(jù)信息及狀態(tài)碼。
timeout :給 Ajax 請(qǐng)求設(shè)置一個(gè)超時(shí)是時(shí)間,單位是毫秒。
type :指定請(qǐng)求的方式,GET 或者 POST,默認(rèn)值是 GET。其它如 PUT 和 DELETE 方式也可以用,但并不是所有瀏覽器都支持。
url :要請(qǐng)求的 URL。
其中 url 選項(xiàng)是所有選項(xiàng)中唯一的一個(gè)必選項(xiàng),其它選項(xiàng)都是可選的。
一些簡(jiǎn)便方法
如果你不需要那么多可配置的選項(xiàng),也不關(guān)心 Ajax 執(zhí)行錯(cuò)誤時(shí)候的相關(guān)處理,jQuery 同樣提供了一些非常有用的簡(jiǎn)便方法,以更簡(jiǎn)潔的方式完成 Ajax 請(qǐng)求。其實(shí)這些簡(jiǎn)便寫法只是封裝了 $.ajax,并把某些選項(xiàng)預(yù)先設(shè)定好。
jQuery 提供的簡(jiǎn)便方法如下:
以上每種簡(jiǎn)便方法中都可傳遞如下參數(shù):
url :所請(qǐng)求的 URL,必須提供。
data :向服務(wù)端發(fā)送的數(shù)據(jù),可選。可以是一個(gè)對(duì)象,亦或查詢字符串,如 foo=bar&baz=bim。
一個(gè)回調(diào)函數(shù) :此回調(diào)函數(shù)在請(qǐng)求成功執(zhí)行后被觸發(fā)。可選。該回調(diào)函數(shù)接受服務(wù)端返回的數(shù)據(jù),也包括請(qǐng)求的狀態(tài)碼及原始對(duì)象。
數(shù)據(jù)類型 :服務(wù)端返回?cái)?shù)據(jù)的類型。可選。
下面是三個(gè)簡(jiǎn)便方法的示例:
// 獲取純文本或者 html$.get('/users.php', { userId : 1234 }, function(resp) { console.log(resp);});// 向頁(yè)面中添加腳本,然后執(zhí)行腳本中定義的函數(shù)。$.getScript('/static/js/myScript.js', function() { functionFromMyScript();});// 從服務(wù)端獲取 JSON 格式的數(shù)據(jù)。$.getJSON('/details.php', function(resp) { $.each(resp, function(k, v) { console.log(k + ' : ' + v); });});
$.fn.load
$.fn.load 方法是 jQuery 所有 Ajax 方法中唯一在選擇器結(jié)果集上調(diào)用的方法。$.fn.load 方法從給定的 URL 上獲取信息,然后填充到選擇器結(jié)果集包含的元素中。另外,在 URL 后面還可以附加一些選擇器,jQuery 最終只會(huì)把跟選擇器相匹配的內(nèi)容填充到對(duì)應(yīng)的 HTML 元素中。
下面是示例:
$('#newContent').load('/foo.html');// 或$('#newContent').load('/foo.html #myDiv h1:first', function(html) { alert('加載完畢!');});
Ajax 和 表單
在跟表單打交道方面,jQuery 的 Ajax 更顯神威。最為有用的兩個(gè)方法就是 $.fn.serialize 和 $.fn.serializeArray,下面是它們的用法:
// 將表單中數(shù)據(jù)轉(zhuǎn)化為查詢字符串$('#myForm').serialize();$('#myForm').serializeArray();// 將表單中數(shù)據(jù)轉(zhuǎn)化為對(duì)象數(shù)組,如:[ { name : 'field1', value : 123 }, { name : 'field2', value : 'hello world' }]
使用 JSONP
JSON 的本質(zhì)其實(shí)是一種跨站點(diǎn)腳本注入。現(xiàn)在有很多比較好的網(wǎng)站都提供了 JSONP 服務(wù),允許我們用他們預(yù)先定義好的 API 獲取他們的數(shù)據(jù)。下面是一個(gè)示例,來(lái)源于 http://www.giantflyingsaucer.com/blog/?p=2682
服務(wù)端代碼:
<?php header("content-type: text/javascript"); if(isset($_GET['name']) && isset($_GET['callback'])) { $obj->name = $_GET['name']; $obj->message = "Hello " . $obj->name; echo $_GET['callback']. '(' . json_encode($obj) . ');'; }?>
客戶端代碼:
$.ajax({ url: 'http://otherDomail.com:8080/JSONP/jsonp-demo.php', data: {name: 'Super man'}, dataType: 'jsonp', jsonp: 'callback', success: function( response ) { console.log( response.message ); }});
jQuery 把 JSONP 的實(shí)現(xiàn)細(xì)節(jié)隱藏在幕后,我們要做的就是告訴 jQuery 服務(wù)端定義好的函數(shù)名以及我們請(qǐng)求的數(shù)據(jù)類型是 JSONP,其它方面和普通的 Ajax 請(qǐng)求沒(méi)什么區(qū)別。
Ajax 事件
很多時(shí)候我們都需要在 Ajax 請(qǐng)求開(kāi)始或結(jié)束時(shí)做一些操作,例如顯示或隱藏一個(gè) loading… 圖片。這些工作本可以在每個(gè) Ajax 請(qǐng)求中各自實(shí)現(xiàn),但是 jQuery 提供了更好的方法,你可以像綁定普通事件一樣綁定 Ajax 事件。若要參閱全部事件列表,可訪問(wèn) http://docs.jquery.com/Ajax_Events。下面是簡(jiǎn)單示例:
$('#loading_indicator') .ajaxStart(function() { $(this).show(); }) .ajaxStop(function() { $(this).hide(); });
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注