讀古今文學網 > 鋒利的jQuery(第2版) > 第6章 jQuery與Ajax的應用 >

第6章 jQuery與Ajax的應用

Ajax全稱為「Asynchronous JavaScript and XML」(異步JavaScript和XML),它並不是指一種單一的技術,而是有機地利用了一系列交互式網頁應用相關的技術所形成的結合體。它的出現,揭開了無刷新更新頁面的新時代,並有代替傳統的Web方式和通過隱藏的框架來進行異步提交的趨勢,是Web開發應用的一個里程碑。

6.1 Ajax的優勢和不足

6.1.1 Ajax的優勢
1.不需要插件支持

Ajax不需要任何瀏覽器插件,就可以被絕大多數主流瀏覽器所支持,用戶只需要允許JavaScript在瀏覽器上執行即可。

2.優秀的用戶體驗

這是Ajax技術的最大優點,能在不刷新整個頁面的前提下更新數據,這使得Web應用程序能更為迅速地回應用戶的操作。

3.提高Web程序的性能

與傳統模式相比,Ajax模式在性能上的最大區別就在於傳輸數據的方式,在傳統模式中,數據提交是通過表單(Form)來實現的,而數據獲取是靠全頁面刷新來重新獲取整頁的內容。Ajax模式只是通過XMLHttpRequest對像向服務器端提交希望提交的數據,即按需發送。

4.減輕服務器和帶寬的負擔

Ajax的工作原理相當於在用戶和服務器之間加了一個中間層,使用戶操作與服務器響應異步化。它在客戶端創建Ajax引擎,把傳統方式下的一些服務器負擔的工作轉移到客戶端,便於客戶端資源來處理,減輕服務器和帶寬的負擔。

6.1.2 Ajax的不足

世界上並沒有完美的事物,同樣Ajax也並不是一項非常完美的技術。Ajax主要有以下幾點不足之處。

1.瀏覽器對XMLHttpRequest對象的支持度不足

Ajax的不足之一首先來自於瀏覽器。Internet Explorer在5.0及以後的版本才支持XMLHttpRequest對像(現階段大部分客戶端上的IE瀏覽器是IE 6及以上),Mozilla、Netscape等瀏覽器支持XMLHttpRequest則更在其後。為了使得Ajax應用能在各個瀏覽器中正常運行,程序員必須花費大量的精力編碼以兼顧各個瀏覽器之間的差別,來讓Ajax應用能夠很好地兼容各個瀏覽器。這使得Ajax開發的難度比普通的Web開發高出很多,許多程序員因此對Ajax望而生畏。

2.破壞瀏覽器前進、"後退"按鈕的正常功能

在傳統的網頁中,用戶經常會習慣性的使用瀏覽器自帶的「前進」和「後退」按鈕,然而Ajax改變了此Web瀏覽習慣。在Ajax中「前進」和「後退」按鈕的功能都會失效,雖然可以通過一定的方法(添加錨點)來使得用戶可以使用「前進」和「後退」按鈕,但相對於傳統的方式卻麻煩了很多,對於大多數程序員來說寧可放棄前進、後退的功能,也不願意在繁瑣的邏輯中去處理該問題。然而,對於用戶來說,他們經常會碰到這種情況,當單擊一個按鈕觸發一個Ajax交互後又覺得不想這樣做,接著就去習慣性地單擊「後退」按鈕,結果發生了最不願意看到的結果,瀏覽器後退到了先前的一個頁面,通過Ajax交互得到的內容完全消失了。

3.對搜索引擎的支持的不足

對於搜索引擎的支持也是Ajax的一項缺憾。通常搜索引擎都是通過爬蟲程序來對互聯網上的數以億計的海量數據來進行搜索整理的,然而爬蟲程序現在還不能理解那些奇怪的JavaScript代碼和因此引起的頁面內容的變化,這使得應用Ajax的站點在網絡推廣上相對於傳統站點明顯處於劣勢。

4.開發和調試工具的缺乏

JavaScript是Ajax的重要組成部分,在目前,由於缺少很好的JavaScript開發和調試工具,使很多Web開發者對JavaScript望而生畏,這對於編寫Ajax代碼就更加困難了。同時,目前許多Web開發者已經習慣使用可視化的工具,對親自動手編寫代碼有畏懼感,這也在一定程度上影響了大家對Ajax的應用。

6.2 Ajax的XMLHttpRequest對像

Ajax的核心是XMLHttpRequest對象,它是Ajax實現的關鍵——發送異步請求、接收響應及執行回調都是通過它來完成的。XMLHttpRequest對像最早是在Microsoft Internet Explorer 5.0 ActiveX組件中被引入的,之後各大瀏覽器廠商都以JavaScript內置對象的方式來實現XMLHttpRequest對象。雖然大家對它的實現方式有所區別,但是絕大多數瀏覽器都提供了類似的屬性和方法,而且在實際腳本編寫方法上的區別也不大,實現得到的效果也基本相同。目前W3C組織正致力於制定一個各瀏覽器廠商可以統一遵照執行的XMLHttpRequest對像標準,用來推進Ajax技術的推廣與發展。

XMLHttpRequest對像提供了一個相對精簡易用的API,本書在附錄C中進行了詳細介紹,讀者可以自行查看。

6.3 安裝Web環境——AppServ

由於講解後面的Ajax方法需要與Web服務器端進行交互,因此這裡將引用一個工具包——AppServ,它是PHP網頁架站工具組合包,能夠幫助初學者快速完成網頁架站。AppServ所包含的軟件有Apache、Apache Monitor、PHP、MySQL、PHP-Nuk和phpMy Admin。

1.下載AppServ

下載地址為:http://www.appservnetwork.com。

2.安裝AppServ

安裝AppServ非常簡單,只要連續輕鬆地單擊「Next」按鈕,輸入網址、電子郵箱、密碼等常用信息即可。端口默認為80,當然也可以在安裝時進行修改。

3.配置示例程序

將本書提供的示例程序複製到安裝好後的AppServ\www文件夾中,然後在地址欄輸入「http://localhost/Ch6/php/」,即可顯示圖6-1所示的頁面。

圖6-1 AppServ下的Ajax示例

單擊相應文件夾,選定HTML頁面,即可運行相應的Ajax示例。

注意:本書還提供了另外兩種主流語言JSP和ASP編寫的對應的示例程序,讀者可以自行配置相應環境進行測試和學習。

6.4 編寫第1個Ajax例子

在正式接觸jQuery的Ajax操作之前,先看一個用傳統的JavaScript實現的Ajax例子。例子描述:單擊一個按鈕,然後通過傳統的JavaScript的Ajax的方式從服務器端取回一個「Hello Ajax!」的字符串並顯示在頁面上。

首先在前台頁面中書寫HTML代碼,代碼如下:

<button>按鈕用來觸發Ajax,id為「resText」的元素用來顯示從服務器返回的HTML文本。

接下來的任務就是完成Ajax函數,實現步驟如下。

(1)定義一個函數,通過該函數來異步獲取信息,代碼如下:

(2)聲明一個空對像用來裝入XMLHttpRequest對象,代碼如下:

(3)給XMLHttpRequest對像賦值,代碼如下:

IE 5、IE 6是以ActiveXObject的方式引入XMLHttpRequest對象的,而其他瀏覽器的XMLHttpRequest對象是window的子對象。

(4)實例化成功後,使用open方法初始化XMLHttpRequest對象,指定HTTP方法和要使用的服務器URL,代碼如下:

默認情況下,使用XMLHttpRequest對像發送的HTTP請求是異步進行的,但是可以顯式地把async參數設置為true,如上面代碼所示。

(5)因為要做一個異步調用,所以需要註冊一個XMLHttpRequest對像將調用的回調事件處理器當它的readyState值改變時調用。當readyState值被改變時,會激發一個readystatechange事件,可以使用onreadystatechange屬性來註冊該回調事件處理器,代碼如下:

(6)使用send方法發送該請求,因為這個請求使用的是HTTP的GET方式,所以可以在不指定參數或使用null參數的情況下調用send方法,代碼如下:

當請求狀態改變時,XMLHttpRequest對像調用onreadystatechange屬性註冊的事件處理器。因此,在處理該響應之前,事件處理器應該首先檢查readyState的值和HTTP狀態。當請求完成加載(readyState值為4)並且響應已經成功(HTTP狀態值為200)時,就可以調用一個JavaScript函數來處理該響應內容,代碼如下:

最後,如果單擊「Ajax提交」按鈕後發現網頁上出現了「Hello Ajax!」,那麼就完成了第1個Ajax調用。如圖6-2所示。

圖6-2 第1個Ajax示例

以上就是實現XMLHttpRequest對像使用的所有細節,它不必將Web頁面的所有內容都發送到服務器,而是按需發送。使用JavaScript啟動一個請求並處理相應的返回值,然後使用瀏覽器的DOM方法更新頁面中的數據。顯然,這種無刷新的模式能給網站帶來更好的用戶體驗。但是XMLHttpRequest對象的很多屬性和方法,對於想快速入門Ajax的人來說,似乎並不是個容易的過程。

幸運的是,jQuery提供了一些日常開發中需要的快捷操作,例如load、ajax、get和post等,使用jQuery開發Ajax將變得極其簡單。這樣開發人員就可以將程序開發集中在業務和用戶體驗上,而不需要理會那些繁瑣的XMLHttpRequest對象。下面開始介紹jQuery中的Ajax。

6.5 jQuery中的Ajax

jQuery對Ajax操作進行了封裝,在jQuery中$.ajax方法屬於最底層的方法,第2層是load、$.get和$.post方法,第3層是$.getScript和$.getJSON方法。首先介紹第2層的方法,因為其使用頻率很高。

6.5.1 load方法
1.載入HTML文檔

load方法是jQuery中最為簡單和常用的Ajax方法,能載入遠程HTML代碼並插入DOM中。它的結構為:

load方法參數解釋如表6-1所示。

表6-1 load方法參數解釋

參 數 名 稱類  型說  明urlString請求HTML頁面的URL地址data(可選)Object發送至服務器的key/value數據callback(可選)Function請求完成時的回調函數,無論請求成功或失敗

首先構建一個被load方法加載並追加到頁面中的HTML文件,名字為test.html,HTML代碼如下:

然後新建一個空白頁面,在上面添加兩個元素:<button>按鈕用來觸發Ajax事件,id為「resText」的元素用來顯示追加的HTML內容。HTML代碼如下:

接下來就可以開始編寫jQuery代碼了。等DOM元素加載完畢後,通過單擊id為「send」的按鈕來調用load方法,然後將test.html的內容加載到id為「resText」的元素裡。

jQuery代碼如下:

當按鈕被單擊後,出現圖6-3所示的界面。

顯然,load方法完成了原本很繁瑣的工作。開發人員只需要使用jQuery選擇器為HTML片段指定目標位置,然後將要加載的文件的URL作為參數傳遞給load方法即可。當單擊按鈕後,test.html頁面的HTML內容就會被加載並插入主頁面<p></p>的元素中。

注意:test.html頁面裡並沒有添加樣式,但現在加載的內容有樣式了。這些樣式是在主頁面中添加的,即主頁面相應的樣式會立即應用到新加載的內容上。

2.篩選載入的HTML文檔

上個例子是將test.html頁面中的內容都加載到id為「resText」的元素裡。如果只需要加載test.html頁面內的某些元素,那麼可以使用load方法的URL參數來達到目的。通過為URL參數指定選擇符,就可以很方便地從加載過來的HTML文檔裡篩選出所需要的內容。

load方法的URL參數的語法結構為:"url selector"。注意,URL和選擇器之間有一個空格。

例如只需要加載test.html頁面中class為「para」的內容,可以使用如下代碼來完成:

運行效果如圖6-4所示。

3.傳遞方式

load方法的傳遞方式根據參數data來自動指定。如果沒有參數傳遞,則採用GET方式傳遞;反之,則會自動轉換為POST方式。關於GET和POST傳遞方式的區別,將在後面進行講解。

圖6-3 load方法調用成功

圖6-4 用load方法加載一部分HTML元素

4.回調參數

對於必須在加載完成後才能繼續的操作,load方法提供了回調函數(callback),該函數有3個參數,分別代表請求返回的內容、請求狀態和XMLHttpRequest對象,jQuery代碼如下:

注意:在load方法中,無論Ajax請求是否成功,只要當請求完成(complete)後,回調函數(callback)就被觸發。對應下面將介紹的$.ajax方法中的complete回調函數。

6.5.2 $.get方法和$.post方法

load方法通常用來從Web服務器上獲取靜態的數據文件,然而這並不能體現Ajax的全部價值。在項目中,如果需要傳遞一些參數給服務器中的頁面,那麼可以使用$.get或者$.post方法(或者是後面要講解的$.ajax方法)。

注意:$.get和$.post方法是jQuery中的全局函數,而在此之前講的jQuery方法都是對jQuery對像進行操作的。

1.$.get方法

$.get方法使用GET方式來進行異步請求。

它的結構為:

$.get方法參數解釋如表6-2所示。

表6-2 $.get方法參數解釋

參 數 名 稱類  型說  明urlString請求的HTML頁的URL地址data(可選)Object發送至服務器的key/value數據會作為QueryString附加到請求URL中callback(可選)Function載入成功時回調函數(只有當Response的返回狀態是success才調用該 方法)自動將請求結果和狀態傳遞給該方法type(可選)String服務器端返回內容的格式,包括xml、html、script、json、text和_default

下面是一個評論頁面的HTML代碼,通過該段代碼來介紹$.get方法的使用。

本段代碼將生成圖6-5所示的頁面。

將姓名和內容填寫好後,就可以準備提交評論了。如圖6-6所示。

圖6-5 評論初始化頁面

圖6-6 填寫好數據

(1)使用參數

首先,需要確定請求頁面的URL地址。代碼如下:

然後,在提交之前,需要獲取「姓名」和「內容」的值作為data參數傳遞給後台。

代碼如下:

如果服務器端接收到傳遞的data數據並成功返回,那麼就可以通過回調函數將返回的數據顯示到頁面上。

$.get方法的回調函數只有兩個參數,代碼如下:

data參數代表請求返回的內容,textStatus參數代表請求狀態,而且回調函數只有當數據成功返回(success)後才被調用,這點與load方法不一樣。

(2)數據格式

服務器返回的數據格式可以有多種,它們都可以完成同樣的任務。以下是幾種返回格式的對比。

 HTML片段

由於服務器端返回的數據格式是HTML片段,因此並不需要經過處理就可以將新的HTML數據插入到主頁面中。jQuery代碼如下:

HTML片段實現起來只需要很少的工作量,但這種固定的數據結構並不一定能夠在其他的Web應用程序中得到重用。

 XML文檔

由於服務器端返回的數據格式是XML文檔,因此需要對返回的數據進行處理,前面的章節已經介紹過jQuery強大的DOM處理能力,處理XML文檔與處理HTML文檔一樣,也可以使用常規的attr、find、filter以及其他方法。jQuery代碼如下:

返回數據格式為XML文檔的過程實現起來比HTML片段要稍微複雜些,但XML文檔的可移植性是其他數據格式無法比擬的,因此以這種格式提供的數據的重用性將極大提高。例如del.icio.us(http://del.icio.us),Flickr(http://flickr.com)和某些開放平台都是以XML格式輸出數據,讀者可以利用它們提供的API,將獲得的內容整合到自己的網站中(Mashup應用)。不過,XML文檔體積相對較大,與其他文件格式相比,解析和操作它們的速度要慢一些。

注意:由於期待服務器端返回的數據格式是XML文檔,因此需要在服務端設置Content-Type類型,代碼如下:header("Content-Type:text/xml; charset=utf-8"); // php

 JSON文件

之所以會出現這種數據格式的文件,很大程度上是因為XML文檔體積大和難以解析。JSON文件和XML文檔一樣,也可以方便的被重用。而且,JSON文件非常簡潔,也容易閱讀。想瞭解更多的JSON文檔知識,可以訪問http://json.org/網址。

由於服務器端返回的數據格式是JSON文件,因此需要對返回的數據進行處理之後,才可以將新的HTML數據添加到主頁面中。jQuery代碼如下:

在上面的代碼中,將$.get方法的第4個參數(type)設置為「json」來代表期待服務器端返回的數據格式。

注意:(1)在不遠的將來,新版的JavaScript中XML將會和JSON一樣容易解析,相信到時候通用且容易解析的XML將會成為主流的數據交換格式。不過在它到來之前,JSON依然有很強的生命力。(2)JSON的格式非常嚴格,構建的JSON文件必須完整無誤,任何一個括號的不匹配或者缺少逗號,都會導致頁面上的腳本終止運行,甚至還會帶來其他更加嚴重的負面影響。比如,我們返回的數據都必須要有雙引號,必須是:{ "username" : "張三" },而不能是:{ username:"張三"}。

以上3種返回方式都可以達到圖6-7所示的效果。

圖6-7 將返回的數據添加到頁面上

通過對3種數據格式的優缺點進行分析,可以得知在不需要與其他應用程序共享數據的時候,使用HTML片段來提供返回數據一般來說是最簡單的;如果數據需要重用,那麼JSON文件是不錯的選擇,它在性能和文件大小方面具有優勢;而當遠程應用程序未知時,XML文檔是明智的選擇,它是Web服務領域的「世界語」。具體選擇哪種數據格式,並沒有嚴格的規定,讀者可以根據需求來選擇最適合的返回格式來進行開發。

2.$.post方法

它與$.get方法的結構和使用方式都相同,不過它們之間仍然有以下區別。

 GET請求會將參數跟在URL後進行傳遞,而POST請求則是作為HTTP消息的實體內容發送給Web服務器。當然,在Ajax請求中,這種區別對用戶是不可見的。

 GET方式對傳輸的數據有大小限制(通常不能大於2KB),而使用POST方式傳遞的數據量要比GET方式大得多(理論上不受限制)。

 GET方式請求的數據會被瀏覽器緩存起來,因此其他人就可以從瀏覽器的歷史記錄中讀取到這些數據,例如賬號和密碼等。在某種情況下,GET方式會帶來嚴重的安全性問題,而POST方式相對來說就可以避免這些問題。

 GET方式和POST方式傳遞的數據在服務器端的獲取也不相同。在PHP中,GET方式的數據可以用$_GET獲取,而POST方式可以用$_POST獲取。兩種方式都可以用$_REQUEST來獲取。

由於POST和GET方式提交的所有數據都可以通過$_REQUEST來獲取,因此只需要改變jQuery函數,就可以將程序在GET請求和POST請求之間切換。代碼如下:

另外,當load方法帶有參數傳遞時,會使用POST方式發送請求。因此也可以使用load方法來完成同樣的功能。代碼如下:

上面使用load、$.get和$.post方法完成了一些常規的Ajax程序,如果還需要編寫一些複雜的Ajax程序,那麼就要用到jQuery中的$.ajax方法。$.ajax方法不僅能實現與load、$.get和$.post方法同樣的功能,而且還可以設定beforeSend(提交前回調函數)、error(請求失敗後處理)、success(請求成功後處理)以及complete(請求完成後處理)回調函數,通過這些回調函數,可以給用戶更多的Ajax提示信息。另外,還有一些參數,可以設置Ajax請求的超時時間或者頁面的「最後更改」狀態等。關於$.ajax方法將在後面的章節中進行講解。

6.5.3 $.getScript方法和$.getJson方法
1.$.getScript

有時候,在頁面初次加載時就取得所需的全部JavaScript文件是完全沒有必要的。雖然可以在需要哪個JavaScript文件時,動態地創建<script>標籤,jQuery代碼如下:

或者

但這種方式並不理想。為此,jQuery提供了$.getScript方法來直接加載.js文件,與加載一個HTML片段一樣簡單方便,並且不需要對JavaScript文件進行處理,JavaScript文件會自動執行。

jQuery代碼如下:

當「加載」按鈕被單擊後,出現如圖6-8所示的效果。

圖6-8 $.getScript('test.js')方法調用成功

與其他Ajax方法一樣,$.getScript方法也有回調函數,它會在JavaScript文件成功載入後運行。例如想載入jQuery官方顏色動畫插件(jquery.color.js),成功後給元素綁定顏色變化動畫,就可以用到$.getScript方法的回調函數。代碼如下:

當jquery.color.js動畫插件加載完畢後,單擊id為「go」按鈕時,class為block的元素就有了顏色動畫變化。

2.$.getJSON

$.getJSON0方法用於加載JSON文件,與$.getScript方法的用法相同。

jQuery代碼如下:

當單擊「加載」按鈕後,網頁上看不到任何效果。雖然函數加載了JS0N文件,但是並沒有告訴JavaScript對返回的數據如何處理。為此,jQuery提供了回調函數,在回調函數里處理返回的數據。代碼如下:

可以在函數中通過data變量來遍歷相應的數據,也可以使用迭代方式為每個項構建相應的HTML代碼。雖然在這裡可以使用傳統的for循環來實現,但既然是講解jQuery,那麼還是使用jQuery裡的方法。jQuery提供了一個通用的遍歷方法$.each,可以用於遍歷對像和數組。

$.each函數不同於jQuery對象的each方法,它是一個全局函數,不操作jQuery對象,而是以一個數組或者對像作為第1個參數,以一個回調函數作為第2個參數。回調函數擁有兩個參數:第1個為對象的成員或數組的索引,第2個為對應變量或內容。代碼如下:

在上面的代碼中,當返回數據成功後,首先清空id為「resText」的元素的內容,以便重新構造新的HTML,然後通過$.each循環函數依次遍歷每個項,並將遍歷出來的內容構建成HTML代碼拼接起來,最後將構建好的HTML添加到id為「resText」的元素中。

當「加載」按鈕被單擊後,出現如圖6-9所示的效果。

圖6-9 $.getJSON('test.json')函數執行成功

不僅如此,還能通過使用JSONP形式的回調函數來加載其他網站的JSON數據,例如從圖片網站(http://Flickr.com)搜索汽車類別的4張最新圖片。代碼如下:

上面的代碼中再次用到全局函數$.each來遍歷數據,因為只需要4張圖片,所以當i=3的時候就需要退出循環。在$.each函數中,如果需要退出each循環,只要返回false即可。

當「加載」按鈕被單擊後,從Flickr網站加載的4張最新的汽車圖片就會被添加到頁面中。效果如圖6-10所示。

圖6-10 加載Flickr網站的圖片

注意:(1)jQuery將自動把URL裡的回調函數,例如「url?callback=?」中的後一個「?」替換為正確的函數名,以執行回調函數。(2)JSONP(JSON with Padding)是一個非官方的協議,它允許在服務器端集成Script tags返回至客戶端,通過JavaScript Callback的形式實現跨域訪問。由於JSON只是一種含有簡單括號結構的純文本,因此許多通道都可以交換JSON消息。而由於同源策略的限制,開發人員不能在與外部服務器進行通信的時候使用XMLHttpRequest。而JSONP是一種可以繞過同源策略的方法,即通過使用JSON與<script>標記相結合的方法,從服務器端直接返回可執行的JavaScript函數調用或者JavaScript對象。目前JSONP已經成為各大公司的Web應用程序跨域首選,例如Youtube GData、Google Social Graph、Digg、豆瓣、Del.icio.us等。

6.5.4 $.ajax方法

$.ajax方法是jQuery最底層的Ajax實現。

它的結構為:

該方法只有1個參數,但在這個對象裡包含了$.ajax方法所需要的請求設置以及回調函數等信息,參數以key/value的形式存在,所有參數都是可選的,常用參數如表6-3所示。

表6-3 $.ajax方法常用參數解釋

如果需要使用$.ajax方法來進行Ajax開發,那麼上面這些常用的參數都必須瞭解。此外,$.ajax方法還有其他參數,讀者可以參考附錄D的具體介紹。

前面用到的$.load、$.get、$.post、$.getScript和$.getJSON這些方法,都是基於$.ajax方法構建的,$.ajax方法是jQuery最底層的Ajax實現,因此可以用它來代替前面的所有方法。

例如,可以使用下面的jQuery代碼代替$.getScript方法:

再例如,可以使用以下jQuery代碼來代替$.getJSON方法:

6.6 序列化元素

1.serialize方法

做項目的過程中,表單是必不可少的,經常用來提供數據,例如註冊、登錄等。常規的方法是使表單提交到另一個頁面,整個瀏覽器都會被刷新,而使用Ajax技術則能夠異步地提交表單,並將服務器返回的數據顯示在當前頁面中。

前面在講解$.get和$.post方法的時候,表單的HMTL代碼如下:

為了獲取姓名和內容,必須將字段的值逐個添加到data參數中。代碼如下:

這種方式在只有少量字段的表單中,勉強還可以使用,但如果表單元素越來越複雜,使用這種方式在增大工作量的同時也使表單缺乏彈性。jQuery為這一常用的操作提供了一個簡化的方法——serialize。與jQuery中其他方法一樣,serialize方法也是作用於一個jQuery對象,它能夠將DOM元素內容序列化為字符串,用於Ajax請求。通過使用serlialize方法,可以把剛才的jQuery代碼改為如下:

當單擊「提交」按鈕後,也能達到同樣的效果。如圖6-11所示。

圖6-11 使用serialize方法

即使在表單中再增加字段,腳本仍然能夠使用,並且不需要做其他多餘工作。

需要注意的是,$.get方法中data參數不僅可以使用映射方式,如以下jQuery代碼:

也可以使用字符串方式,如以下jQuery代碼:

用字符串方式時,需要注意對字符編碼(中文問題),如果不希望編碼帶來麻煩,可以使用serialize方法,它會自動編碼。

因為serialize方法作用於jQuery對象,所以不光只有表單能使用它,其他選擇器選取的元素也都能使用它,如以下jQuery代碼:

把復選框和單選框的值序列化為字符串形式,只會將選中的值序列化。

2.serializeArray方法

在jQuery中還有一個與serialize類似的方法——serializeArray,該方法不是返回字符串,而是將DOM元素序列化後,返回JSON格式的數據。jQuery代碼如下:

通過console.log方法輸出fields對象,然後在Firebug中查看該對象,如圖6-12所示。

圖6-12 用Firebug查看對像

既然是一個對象,那麼就可以使用$.each函數對數據進行迭代輸出。代碼如下:

3.$.param方法

它是serialize方法的核心,用來對一個數組或對像按照key/value進行序列化。

比如將一個普通的對象序列化:

6.7 jQuery中的Ajax全局事件

jQuery簡化Ajax操作不僅體現在調用Ajax方法和處理響應方面,而且還體現在對調用Ajax方法的過程中的HTTP請求的控制。通過jQuery提供的一些自定義全局函數,能夠為各種與Ajax相關的事件註冊回調函數。例如當Ajax請求開始時,會觸發ajaxStart方法的回調函數;當Ajax請求結束時,會觸發ajaxStop方法的回調函數。這些方法都是全局的方法,因此無論創建它們的代碼位於何處,只要有Ajax請求發生時,就會觸發它們。在前面例子中,遠程讀取Flickr.com網站的圖片速度可能會比較慢,如果在加載的過程中,不給用戶提供一些提示和反饋信息,很容易讓用戶誤認為按鈕單擊無用,使用戶對網站失去信心。

此時,就需要為網頁添加一個提示信息,常用的提示信息是「加載中…」,代碼如下:

然後用CSS控制元素隱藏,當Ajax請求開始的時候,將此元素顯示,用來提示用戶Ajax請求正在進行。當Ajax請求結束後,將此元素隱藏。代碼如下:

這樣一來,在Ajax請求過程中,只要圖片還未加載完畢,就會一直顯示「加載中…」的提示信息,看似很簡單的一個改進,卻將極大地改善用戶的體驗。效果如圖6-13所示。

如果在此頁面中的其他地方也使用Ajax,該提示信息仍然有效,因為它是全局的。如圖6-14所示。

圖6-13 顯示"加載中…"的提示信息

圖6-14 demo2也使用同一個提示信息

jQuery的Ajax全局事件中還有幾個方法,也可以在使用Ajax方法的過程中為其帶來方便。如表6-4所示。

表6-4 另外幾個方法

方 法 名 稱說  明ajaxComplete(callback)Ajax請求完成時執行的函數ajaxError(callback)Ajax請求發生錯誤時執行的函數,捕捉到的錯誤可以作為最後一個參數傳遞ajaxSend(callback)Ajax請求發送前執行的函數ajaxSuccess(callback)Ajax請求成功時執行的函數

注意:1,如果想使某個Ajax請求不受全局方法的影響,那麼可以在使用$.ajax(options)方法時,將參數中的global設置為false,jQuery代碼如下:

2,在jQuery1.5版本之後,如果Ajax請求不觸發全局方法,那麼可以設置:

具體原因請查看:http://bugs.jquery.com/ticket/8338

6.8 基於jQuery的Ajax聊天室程序

通過前面的介紹,相信讀者已經對jQuery的Ajax有了較深的認識。下面,將講解一個較為複雜的Ajax實例,可以幫助讀者更好地掌握Ajax的精髓——一個基於Ajax無需刷新技術開發的聊天室程序,該程序允許多用戶在網頁上聊天,並且可以實時地更新信息。

6.8.1 基本設想

首先設計聊天室的外觀,如圖6-15所示。

圖6-15 聊天室外觀

6.8.2 設計數據庫

這裡使用MySql數據庫來存儲信息。

首先構建一個聊天信息表messages,它有4個字段,即消息編號(id)、姓名(user)、內容(msg)以及一個數字時間戳(time)。下面是創建該表的SQL代碼:

6.8.3 服務器端處理

服務器端主要用來處理用戶提交的信息以及輸出返回。

 首先需要在服務器端鏈接數據庫。

 其次如果有用戶提交新信息,則把信息插入數據庫,同時刪除舊的數據信息(保持數據庫中只有10條信息)。

 最後從數據庫中獲取新的信息並以XML格式輸出返回。

這裡可以先模擬服務端輸出的XML代碼結構,XML文檔代碼如下:

在這個XML結構中,不光只有消息的實體(包括作者及其聊天信息),還增加了一個「status」標籤和一個「time」標籤。其中「status」標籤用來表示信息請求的狀態,如果值為1,則表示新信息請求成功;如果值為2,則表示請求成功但沒有新信息。「time」標籤用來記錄信息請求的時間,可以被用來讀取該時間戳後用戶提交的新數據。

6.8.4 客戶端處理

在客戶端需要做兩項工作。

 首先提交用戶聊天信息,然後處理服務器端返回的聊天信息,將信息實時呈現出來。

 每隔一定時間發起查詢數據庫中聊天記錄的請求,然後處理服務端返回的聊天信息,將信息實時呈現出來。

(1)提交用戶聊天信息

使用POST方式向服務器發送請求,將用戶填寫的姓名和內容等數據傳遞到服務器端,在服務器端處理後返回相應的XML數據,然後使用回調函數處理服務器端返回的這些數據,並將新信息追加到客戶端的消息顯示區中。

(2)瀏覽器每隔一定時間更新數據

增加一個定時器,並且每隔一定時間調用一次。然後使用回調函數處理服務器端返回的XML數據,並將新信息追加到客戶端的消息顯示區中。

由於上面的兩項工作都需要對XML文檔進行解析,然後追加到信息顯示區,因此可以將此操作進行封裝,以便於重複利用。在設計該XML文檔操作函數時,應注意通過狀態(「status」標籤)和時間戳(「time」標籤)來控制獲取聊天信息。

6.8.5 客戶端代碼
1.客戶端HTML代碼

首先建立一個HTML頁面。從前面的外觀設計可以知道頁面需要一個外圍<p>、一個消息段落(用來顯示聊天信息)、姓名文本框、消息文本、提交按鈕的表單和一個加載信息時的提示。HTML代碼如下:

當用戶第1次進入聊天室的時候,顯示效果如圖6-16所示。

圖6-16 初始化頁面效果

2.客戶端jQuery代碼

首先,需要設置當前消息的時間戳為0,並且調用函數來加載數據庫已有的聊天消息,代碼如下:

然後,為表單添加一個submit事件,代碼如下:

在submit事件函數中,可以使用jQuery的$.post方法來發送一個POST請求,把要傳遞的數據都放入第2個參數中,用{ }包裹,代碼如下:

接下來,如何響應返回的XML呢?為了使代碼能被重用,這裡創建一個處理XML的函數並且調用該函數(在updateMsg方法中,也要用到這個解析XML的函數)。函數如下:

addMessages函數里的具體內容將在後邊實現。

現在就可以列出表單提交的全部代碼了,代碼如下:

在表單提交事件的最後一行添加了「return false;」語句,可以用來阻止瀏覽器提交表單。

現在再看addMessages函數,它是用來處理XML響應信息的。前面講解過,jQuery遍歷XML文檔與遍歷DOM一樣。使用XML文檔中的狀態碼,其代碼如下:

上段代碼中使用$("status",xml)方法來通知jQuery去XML文檔中尋找「status」標籤。如果狀

態代碼為2,則表示完成了請求但沒有新信息需要添加到該客戶端的消息顯示區中,因此使用「return;」語句終止函數調用。如果狀態代碼不為2,則繼續往下執行。

接下來需要為XML的時間戳設定新的值,用來傳遞給後台去查詢新的數據。獲取時間戳的代碼如下:

然後使用$.each函數將XML文檔裡的數據遍歷出來。在示例中,需要顯示到客戶端消息顯示區的元素就是服務器端返回的每一個「message」標籤的實例,每個實例代表一條要顯示的消息。以下代碼展示如何遍歷數據:

得到了所需的數據之後,就可以將其追加到消息顯示區裡。消息顯示窗體的id為「messagewindow」,因此可以使用$("#messagewindow")來選擇到它並且使用prepend方法來追加數據,代碼如下:

將它們整合後,addMessages(xml)函數的代碼如下:

最後,只剩下剛開始調用的函數updateMsg還未完成。該函數的功能是到服務器查詢新信息,並且調用addMessages函數來響應返回的XML文檔,同時需要設置一個間隔時間,讓聊天窗口自動更新。要開始做這些工作,只需要向服務器提交一個時間戳,引用這個$.post調用即可,代碼如下:

在回調函數里,首先應該移除loading消息,可以在這個元素上調用remove方法,代碼如下:

然後,在回調函數中將接受到的XML文檔對像傳遞給addMessages函數,代碼如下:

最後調用JavaScript的setTimeout方法來每隔一定時間執行updateMsg函數。

updateMsg函數的代碼如下:

6.8.6 整合代碼

聊天界面如圖6-17所示。

正如讀者所看到的,僅用了少量的jQuery代碼,就實現了一個完整的基於Ajax的Web聊天室應用程序。用jQuery可以如此簡單的實現一個複雜的Ajax應用,不得不令人歎服。

圖6-17 最終的聊天室程序

6.9 小結

本章首先對Ajax進行了簡介,並且介紹了Ajax的優勢與不足,讓讀者充分瞭解到Ajax的適用範圍。接下來介紹了Ajax的XMLHttpRequest對象,並展示了傳統的Ajax程序的編寫,然後系統地講解了jQuery中的Ajax方法。在介紹了序列化元素和Ajax全局事件兩個重要的概念後,講解了一個稍微複雜的Ajax聊天室程序。