js的動態加載、緩存、更新以及復用 系列有點卡文,放心會繼續的。先來點更基礎的,為js的加載做點鋪墊。
jQuery的ajax本來就很方便了,為啥還要在進一步的封裝呢?這個首先要看項目的具體需求了,如果覺得不需要,那么完全可以直接用jQuery提供的各種ajax的方法。如果像我似地,感覺不太方便的話,那么完全可以按照自己的想法和需求來再次封裝一下。
需求:
1、調用的時候更加的簡單。
2、可以靈活的做各種設置和變化。
3、可以滿足一些通用的需求。比如出錯的時候給出提示。
項目現狀:
做ajax請求的時候,會有一個加載的動畫,在ajax發起的時候要自動開始,加載完畢之后要自動停止。出錯了也要自動停止,並且給出錯誤提示。請求的URL比較固定,按照增刪改查來分類。要可以跨域,也可以不跨域。需要靈活的進行切換。ajax獲得數據的同時,還會附帶一段調試信息,需要顯示出來。有專門的處理函數,但是需要調用。
實現:
直接上代碼吧。
//對ajax的封裝 Nature.Ajax = function (ajax) { //最基礎的一層封裝 //定義默認值 var defaultInfo = { type: "GET", //訪問方式:如果dataPata不為空,自動設置為POST;如果為空設置為GET。 dataType: Nature.sendDataType, //數據類型:JSON、JSONP、text。由配置信息來搞定,便於靈活設置 cache: true, //是否緩存,默認緩存 xhrFields: { //允許跨域訪問時添加cookie。cors跨域的時候需要設置 withCredentials: true }, urlPata: {},//url后面的參數。一定會加在url后面,不會加到form里。 formPata: {},//表單里的參數。如果dataType是JSON,一定加在form里,不會加在url后面;如果dataType是JSONP的話,只能加在url后面。 //url: //依靠上層指定 //timeout: 2000, error: function() { }, //如果出錯,停止加載動畫,給出提示。也可以增加自己的處理程序 success: function() { } //成功后顯示debug信息。也可以增加自己的處理程序 }; //補全ajaxInfo if (typeof ajaxInfo.dataType == "undefined") { ajaxInfo.dataType = defaultInfo.dataType; } if (typeof ajaxInfo.formPata == "undefined") { ajaxInfo.type = "GET"; } else { if (ajaxInfo.dataType == "JSON") { ajaxInfo.type = "POST"; } else { //get或者jsonp ajaxInfo.type = "POST"; } ajaxInfo.data = ajaxInfo.formPata; } if (typeof ajaxInfo.cache == "undefined") { ajaxInfo.cache = defaultInfo.cache; } //處理URL if (typeof ajaxInfo.urlPata != "undefined") { var tmpUrlPara = ""; var para = ajaxInfo.urlPata; for (var key in para) { tmpUrlPara += "&" + key + "=" + para[key]; } if (ajaxInfo.url.indexOf('?') >= 0) { //原地址有參數,直接加 ajaxInfo.url += tmpUrlPara; } else { //原地址沒有參數,變成?再加 ajaxInfo.url += tmpUrlPara.replace('&', '?'); } } //開始執行ajax $.ajax({ type: ajaxInfo.type, dataType: ajaxInfo.dataType, cache: ajaxInfo.cache, xhrFields: { //允許跨域訪問時添加cookie withCredentials: true }, url: ajaxInfo.url, data: ajaxInfo.data, //timeout: 2000, error: function() { //訪問失敗,自動停止加載動畫,並且給出提示 alert("提交" + ajaxInfo.title + "的時候發生錯誤!"); if (typeof top.spinStop != "undefined") top.spinStop(); if (typeof ajaxInfo.error == "function") ajaxInfo.error(); }, success: function (data) { if (typeof(parent.DebugSet) != "undefined") parent.DebugSet(data.debug); //調用顯示調試信息的函數。 if (typeof (ajaxInfo.ctrlId) == "undefined") ajaxInfo.success(data); else { ajaxInfo.success(ajaxInfo.ctrlId, data); } } }); };
這是最底層的封裝,然后是根據URL的封裝,其實就是避免在代碼里到處寫URL的問題。
1 Nature.Data.MetaData = function () { 2 3 var ajax = Nature.Ajax;//簡化一下 4 5 6 /*獲取頁面視圖的元數據*/ 7 this.ajaxGetMeta = function (ajaxData) { 8 9 ajaxData.url = Nature.resourceUrl + "/MetaData/GetMeta.ashx"; 10 ajaxData.cache = false; 11 12 ajax(ajaxData); 13 }; 14 15 16 17 } 18 19 Nature.Data.CusData = function () { 20 21 var ajax = Nature.Ajax; 22 23 34 //獲取客戶數據 35 this.ajaxGetData = function(ajaxData) { 36 37 //增刪改查服務的網址 38 var url = Nature.resourceUrl; 39 if (typeof ajaxData.url == "undefined") 40 url += "/Data/GetData.ashx"; 41 else 42 url += ajaxData.url; 43 44 ajaxData.url = url; 45 ajaxData.cache = false; 46 47 ajax(ajaxData); 48 49 }; 50 51 /*刪除數據*/ 52 this.ajaxDeleteData = function (ajaxData) { 53 var url = Nature.resourceUrl; 54 55 if (typeof ajaxData.url == "undefined") 56 url += "/Data/GetData.ashx"; 57 else 58 url += ajaxData.url; 59 60 ajaxData.url = url; 61 ajaxData.cache = false; 62 63 ajax(ajaxData); 64 }; 65 66 67 }
這個是按照增刪改查的URL地址來定的幾個函數。主要目的就是處理具體的URL,避免代碼里面到處都是URL的混亂問題。
最后就是具體應用的地方了。
1 var load = new Nature.Data.MetaDate(); 2 3 load.ajaxGetMeta({ 4 urlPata: { action: "tree", mdid: 0, dbid: dataBaseId, ProjectID: projectId, cacheKey: 0 }, 5 title: "獲取XXX", 6 success: function (msg) { 7 8 if (typeof top.__cache == "undefined") 9 top.__cache = {};/* 開辟緩存空間 */ 10 11 top.__cache.treeMeta = msg.data; 12 13 create2(msg.data); 14 } 15 });
這樣調用起來就比較簡單了,避免了一些常用且固定的參數的設置,比如type、dataType、cache、url等。可能有些童鞋會想了,不是有$.get和$.post了嗎,比你的更簡潔吧,你還自己折騰啥!
$.get和$.post確實更簡潔,但是不夠靈活,比如cache的設置,有的時候需要緩存,有的時候不需要緩存。再比如type,有的頁面需要跨域,有的地方不需要跨域。有的時候要根據項目來統一設置(切換)。所以我自己折騰了一下。
詳細說明:
默認參數里的幾個屬性的含義。
1、title。ajax有可能出錯,出錯了就應該有個提示。但是一個頁面往往有多個ajax,到底是哪個出錯了?所以我設置了一個title的屬性,在error的時候 alert("提交" + ajaxInfo.title + "的時候發生錯誤!");這樣就比較清晰了,至少按照title的屬性值來find一下,可以快速定位。
2、urlPata和formPata。jQuery的ajax只有一個data的屬性。當get的時候,會把data放到URL里面,傳遞給服務器;當POST的時候,會把data放在form里面,提交給服務器。這個似乎挺好,但是在post的時候,我需要明確的把一些參數放在URL里面,一些參數放在form里面。這個就不能都放在data里面,我還得自己去拼接URL。麻煩還愛出錯。所以我就分成了兩個屬性urlPata和formPata。
urlPata肯定會出現在URL里面。formPata就需要根據情況而定了。JSON的時候會放在form里面,JSONP的時候就只能放在URL里面了。
3、xhrFields。這個就涉及到HTML5.0里面對post跨域的支持問題了。一般提到跨域,想到的都是JSONP,但是JSONP是偽裝成<script>來實現的跨域,由於js並不支持post,所以導致無法實現post的跨域提交。現在HTML5.0解決了這個問題,就是cors。我也是最近幾天才弄明白這個。后來發現jQuery也是支持cors的。jQUery.support.cors = true; 這樣就可以開啟cors。然后在測試的時候發現個問題,出於安全考慮,默認情況下cors的跨域是不會附帶cookie信息的,需要手動設置。於是就出現了xhrFields這一段。當然要完全實現cors,服務器端也需要做相應的設置,這個會在我的《細說跨域那點事》里面有詳細的說明。
4、error。ajax訪問,難免會出現點小意外,有的是服務器返回的值有問題,有時候是服務器報錯了。那么要怎么辦呢?於是就出現了這個error的統一處理函數。在這里首先會根據title屬性給出一個提示,告訴用戶,訪問出錯了。然后會把加載的動畫提示給停掉。一開始在出錯的時候沒有去停止加載動畫,好多用戶就更我說,你那個頁面,轉呀轉呀,轉了n就都沒反應。所以我就加上了這段。
5、success。成功之后,調用顯示調試信息的函數,把調試信息給顯示出來。便於調試和優化。
6、defaultInfo。首先以傳遞過來的ajaxInfo為准,如果有了就按照ajaxInfo的來,如果沒有指定,就使用defaultInfo提供的對應屬性來賦值。就是一個缺省值的作用。
折騰的好處:
一開始error里面,沒有alert的提示,很不可思議吧,但是確實是沒有。后來想想還是加上吧,那么我改一個地方就ok了,不需要到處都去改。后來又加上了停止加載動畫的功能,現在想想,是不是也要把顯示調試信息的給加上呢?有些錯誤也是會返回調試信息的呀。如果加的話,也是只需要改一個地方就ok了。
以前不知道cors,學會cors之后發現要附帶cookie的話,還要加上xhrFields,那好吧,就一個地方加上就行了,也不需要到處去改。
總之,當變化發生的時候,我只需要改一個地方就ok了,我不需要到處去改,還容易漏掉某某。
ps:
這里跳過了一個步驟,就是“緩存”。不是ajax帶的cache,而是類似於本地儲存(Local Storage)的東東。這個以后會詳細說明。