現在的網站,在一個網頁中有非同步請求甚至許多個非同步請求已經不足為奇。Ajax已經成為了現在網站必須的準系統,使網頁應用更接近於案頭應用。
然而,無論有多麼接近,通過用戶端與服務端的一來一回,必定會有等待載入資料的時間。所以,大多數網站都通過一個Gif動態表徵圖或‘Loading...’等字樣來告知使用者資料還在載入中。但有時候這個問題會非常繁瑣和麻煩,要麼將這個‘Loading’顯示在ajax請求之前,然後在ajax成功後隱藏它,或者將它寫在jquery的ajax的全域事件jQuery.ajaxStart()和jQuery.ajaxStop()中來控制整個頁面的ajax狀態。前者方法使用起來太瑣碎,每個請求都要寫一遍這個‘Loading’,而且無論請求成功或失敗都需要隱藏它。後者是全域的,也就是整個頁面的請求狀態,有時候無法滿足在局部顯示載入狀態的要求。
為瞭解決這些問題,我開發了jQuery的外掛程式,名為:Ajax請求狀態管理器。使用這個外掛程式可以讓loading不再那麼麻煩了。你可以在觸發ajax請求前,用該外掛程式事先添加寫好所有請求,你要做的只是在使用者互動的事件中執行下.request()方法。你可以將一個頁面上所有請求設定為獨立顯示loading,也可以設定為全域顯示(只顯示一個loading)。下面是外掛程式的具體使用方法:
自訂loading的css樣式:
.state-loading { background: #fff url(images/icon-ajax-loader.gif) ... }
引用jquery最新版本檔案:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
注意:該外掛程式只在jquery1.4.4及之後的版本中測試通過。
引用Ajax請求狀態管理器外掛程式檔案:
<script src="js/jquery-ajaxloader.js"></script>
在jquery的ready事件中執行.install()方法:
$.loader.install( className, isGlobal );
參數說明:
className:string,表示你自訂的loading的class名稱,比如上面css定義的state-loading。
isGlobal:boolean,定義是否是全域顯示還是獨立顯示loading,預設值是true,該參數可以省略。
添加所需的ajax請求參數和成功後的回調方法:
$.loader( key ).add( modules, settings , callback );
參數說明:
key:string,通過這個key來建立或擷取指定模組的載入器。當然,同一個key可以執行多次add()方法來添加不同的module,但是settings和callback是對於這個key是共用的,所以之後添加的settings和callback會覆蓋之前的。
modules:jquery object,一個頁面中同一個請求可以處理多個模組的資料,所以,如果之前install()方法是設定為false的,在執行ajax請求時,添加到這個loader的所有module都會顯示loading狀態。
settings:map,jquery的ajax settings參數,但不要設定ajax事件,這樣會覆蓋外掛程式中的回調方法,預設請求類型為GET。
callback:function,成功後的回呼函數,它有一個參數data,預設是json類型返回的對象。
add()方法返回一個由'module'首碼的字串數組,比如你添加了3個元素,那結果為['module1', 'module2', 'module3']。你可以通過返回的數組來刪除指定的其中一個模組的loading,也可以不指定,也就是全部刪除,當然如果你需要這樣做的話。
remove()方法刪除指定的模組:
$.loader( key ).remove( moduleId );
參數說明:
moduleId:string或者array,指定為string的話會刪除其中一個module,指定為數組會大量刪除模組,如果未指定參數,會將模組全部刪除。
樣本
添加2個模組到名為userinfo的載入器中:
代碼如下 |
複製代碼 |
var id1 = $.loader( 'userinfo' ).add( $( '#userinfo, #top-userinfo' ), { url: 'server/userinfo.php' }, function( data ) { updateContent( $( '#userinfo, #topsection, #footer-userinfo' ), data ); } );
|
再添加一個模組到userinfo的載入器中:
代碼如下 |
複製代碼 |
var id2 = $.loader( 'userinfo' ).add( $('#footer-userinfo') ); var idList = id1.concat( id2 ); // result: [ 'module1', 'module2', 'module3' ] 刪除第2個模組的loading,也就是‘#top-userinfo’: var ret = $.loader( 'userinfo' ).remove( idList[1] ); // result: true, modules: [ 'module1', 'module3' ] 在互動事件中執行.request()方法: $.loader( key ).request(); |
當然,你也可以拋棄之前add的ajax settings和callback,在互動事件中自己寫$.ajax或$.get等。然後在請求前調用$.loader( key ).show(),在回呼函數內調用$.loader( key ).hide()。這樣也可以靈活控制loading的狀態。
樣本
代碼如下 |
複製代碼 |
$( '#getUserInfo' ).bind( 'click', function() { $.loader( 'userinfo' ).request(); });
|
你也可以從新重新寫請求:
代碼如下 |
複製代碼 |
$( '#getUserInfo' ).bind( 'click', function() { $.loader( 'userinfo' ).show(); $.get( 'server/userinfo.php', function( data ) { $.loader( 'userinfo' ).hide(); updateContent( $( '#userinfo, #topsection, #footer-userinfo' ), data ); }) });
|
注意:一個請求反覆觸發時,管理器會執行abor()來阻止之前未完成的請求,重新發布新的請求,然而如果你在頁面中通過jquery的ajaxError事件輸出錯誤資訊,會把該資訊一併認為是錯誤的,所以如果有必要的話,需要你自行過濾。
樣本
代碼如下 |
複製代碼 |
// 輸出錯誤記錄檔 $( 'body' ).bind( 'ajaxError', function( event, xhr, setting, thrownError ) { // 過濾掉 abort 的錯誤資訊 if ( xhr.status === 0 || xhr.readyState === 0 || xhr.statusText === 'abort' ) { return; } $( '#log' ).append( '<p>' + thrownError + '</p>' ); });
|