1. 程式人生 > >jquery easyui tab載入內容的幾種方法

jquery easyui tab載入內容的幾種方法

jQuery Easyui 的tabs外掛有兩種方式載入某個tab(標籤頁)上的內容:“href遠端請求”和“content本地內容”,本文就兩種方式的優缺點進行簡單分析和思考。

兩者特點:

href方式載入資料的特點:
  1. 被載入的頁面只有body元素內部的內容才會被載入,也就是jQuery的ajax請求的只是html片段。
  2. 載入遠端url時有遮罩效果,也就是“等待中……”效果,使用者體驗較好。
  3. 當載入的頁面佈局較為複雜,或者有較多的js指令碼需要執行的時候,編碼往往就需要謹慎了,容易出問題,後面會詳細談。
content方式載入資料的特點:
  1. 比較靈活,你可以在腳本里面拼寫html程式碼,然後賦值給tab的content屬性,不過這種寫法會使得程式碼易讀性變差。
  2. 可以把iframe賦給content,把一個iframe嵌入也就沒有什麼不能完成的了。
  3. 使用iframe會造成客戶端js重複載入,浪費資源,比如說你主頁面要引用easyui的庫,你的iframe也要引用,浪費就產生了。

簡單總結:

根據上面的分析,使用content的方式較為簡潔,而且可以引入iframe來搞定一切,缺點也很明顯,系統較為複雜的話,將帶來極大地資源浪費,只適合較為簡單的頁面系統;

而href方式則對編碼能力要求的稍微高一些,因為html的片段,稍微不注意就會處理不好,不過熟練的話,個人覺得href方式是不二之選。

href常見問題:

1.href只加載目標URL的html片段

這個特性是由jQuery封裝的ajax請求處理機制所決定的,所以目標URL頁面裡不需要有html,head,body等標籤,即使有這些元素,也會被忽略,所以放在head標籤裡面的任何指令碼也不會被引入或者執行。

2.短暫的頁面混亂:

href連結的頁面比較複雜的時候,easyui對其渲染往往需要一個較長的過程,這時候,載入進來的html片段毫無佈局可以,過一會自動會好,這時候easyui已經完成對它的渲染。如何避免這個混亂的過程呢,還得靠easyui的一個基礎外掛——解析器(Parser)。

Parser有個onComplete事件,這個事件就是指easyui對頁面完成渲染時觸發,這樣思路就很清晰了:用一個div遮罩住讓被載入進來的html片段,在onComplete事件中,讓這個div淡出,這時候渲染好的html片段就能美人出浴了,同時還整了個等待中的效果,一舉兩得。這樣要做兩件事:

第一是在要載入的html片段中放一個遮罩用的div:

Html程式碼 複製程式碼 收藏程式碼
  1. <divid="loading"style="position: absolute; z-index: 1000; top: 0px; left: 0px; width: 100%; height: 100%; background: #DDDDDB; text-align: center; padding-top: 20%;"></div>
  1. <divid="loading"style="position: absolute; z-index: 1000; top: 0px; left: 0px; width: 100%; height: 100%; background: #DDDDDB; text-align: center; padding-top: 20%;"></div>

第二是在被載入的html片段尾部處理相關事件:

Js程式碼 複製程式碼 收藏程式碼
  1. function show(){   
  2.     $("#loading").fadeOut("normal"function(){   
  3.         $(this).remove();   
  4.     });   
  5. }       
  6. var delayTime;   
  7. $.parser.onComplete = function(){   
  8. if(delayTime)    
  9.         clearTimeout(delayTime);   
  10.         delayTime = setTimeout(show,500);   
  11.     }  
  1. function show(){  
  2.     $("#loading").fadeOut("normal"function(){  
  3.         $(this).remove();  
  4.     });  
  5. }      
  6. var delayTime;  
  7. $.parser.onComplete = function(){  
  8.     if(delayTime)   
  9.         clearTimeout(delayTime);  
  10.         delayTime = setTimeout(show,500);  
  11.     }  

需要注意的是,如果多個tab頁面都使用了onComplete事件,當前定義的會覆蓋之前定義的。其實每次easyui渲染完成均會呼叫onComplete事件,所以每開啟一個包含easyui控制元件的tab頁,onComplete事件就會被呼叫。

3.html片段的easyui元件相關指令碼莫名地報錯:

其實這個現象是跟第一個現象的原因一樣的,easyui完成對html片段渲染需要一定的時間,頁面越複雜,耗時越長,這時候難以避免html存在的指令碼存在對easyui某些外掛的呼叫,比如datagrid等,這個時候就會報錯,解決方案同上,將這些指令碼放到onComplete事件裡處理,也就保證了渲染完成前,不會被執行。

4.放在window裡面表單驗證的提示資訊會亂串:

這個現象應該是外掛自身的bug,對位置的計算沒有考慮到這些特殊的事情,解決方式可以投機取巧,在開啟window後,讓表單不符合驗證的input獲得焦點就可以了。

5.兩次或者多次載入遠端資料問題:

官方已經說明在1.2.5的版本中已經修正了這個Bug,但是還是有不少人反應會出現兩次載入遠端資料的現象,甚至在1.2.6版本中也會遇到,如果您確實遇到這種情況了,請按以下方式檢查:

  • 遠端資料返回的資料中是否包含class=”easyui-tabs”或者class=”easyui-datagrid”這樣的樣式了, 如果有的話,easyui在獲取html片段後會自動渲染,這時候已經對遠端資料來源做了一次請求;
  • 您是否又用javascript去$(‘#tabsId’).tabs({…});或者$(‘#tabsId’).datagrid({…});去繫結事件或者設定屬性,其實等於又一次渲染了對應控制元件,會再次請求遠端資料。

為什麼會這樣,看看原始碼便知道了:

Js程式碼 複製程式碼 收藏程式碼
  1. $.fn.tabs = function(options, param){   
  2. if (typeof options == 'string') {   
  3. //這個地方的分支很清楚,只有當options為字串的時候,才是直接呼叫控制元件本身提供的方法。 
  4. return $.fn.tabs.methods[options](this, param);   
  5.     }   
  6. //如果options不是字串,直接構造控制元件,inxing渲染。 
  7.     options = options || {};   
  8. returnthis.each(function(){   
  9. var state = $.data(this'tabs');   
  10. var opts;   
  11. if (state) {   
  12.                 opts = $.extend(state.options, options);   
  13.                 state.options = opts;   
  14.             }   
  15. else {   
  16.                 $.data(this'tabs', {   
  17.                     options: $.extend({}, $.fn.tabs.defaults, $.fn.tabs.parseOptions(this), options),   
  18.                     tabs: wrapTabs(this),   
  19.                     selectHis: []   
  20.                 });   
  21.             }   
  22.             buildButton(this);   
  23.             setProperties(this);   
  24.             setSize(this);   
  25.             initSelectTab(this);   
  26.         });   
  27.     };  
  1. $.fn.tabs = function(options, param){  
  2.     if (typeof options == 'string') {  
  3.         //這個地方的分支很清楚,只有當options為字串的時候,才是直接呼叫控制元件本身提供的方法。
  4.         return $.fn.tabs.methods[options](this, param);  
  5.     }  
  6.     //如果options不是字串,直接構造控制元件,inxing渲染。
  7.     options = options || {};  
  8.     returnthis.each(function(){  
  9.         var state = $.data(this'tabs');  
  10.             var opts;  
  11.             if (state) {  
  12.                 opts = $.extend(state.options, options);  
  13.                 state.options = opts;  
  14.             }  
  15.             else {  
  16.                 $.data(this'tabs', {  
  17.                     options: $.extend({}, $.fn.tabs.defaults, $.fn.tabs.parseOptions(this), options),  
  18.                     tabs: wrapTabs(this),  
  19.                     selectHis: []  
  20.                 });  
  21.             }  
  22.             buildButton(this);  
  23.             setProperties(this);  
  24.             setSize(this);  
  25.             initSelectTab(this);  
  26.         });  
  27.     };  

                 因此,直接傳入物件的話,所有控制元件都會重新構造的,tabs多次載入的問題大多數就是這麼發生的。