ExtJS4 源碼解析(一)帶項目分析


     Ext這個東東太大了,能看完就已經很不錯了,完整的源碼分析就不敢說了,大概就涉及了類管理,事件管理,數據結構緩存架構,UI組件核心機制,MVC這幾個方面,只是挑着源碼看的,沒有實際完整的使用.

公司的框架我是借鑒了EXT的結構..站在巨人的肩上我們可以走的更遠,內部的結構我已經改動了,組件的形式去架構不適合咱公司~

     如圖~

     image

 

  • 昨天遇到個問題在mixins(向創建的類中要摻進其它類的信息)多個的時候就出問題了~ 順便就發一下我的源碼分析吧.當然是個人角度,有錯誤歡迎指出.
  • 發幾本EXT的書,以前分析代碼的時候看過了,感覺還行

image

 

EXT3.4 到 4.0改動真心很大…以前是用3.4玩的,后來看到4.0又把代碼給整個重構了一次

 

這里先着重講一下 ExtJs4.0 Class的實現:

ExtJs4.0中,涉及Class實現的主要是Ext Core , Ext.Class, Ext.Base, Ext.ClassManager 這幾個對象

  • Base.js定義了Base類,Base類是ExtJS4.0中所有通過Ext.define定義的類的直接或間接父類,Base類中定義了一些通用的實例與靜態屬性與方法;
  • Class.js文件中定義了Class類,所有通過Ext.define定義的類都是Class的實例(其實是Class構造函數中的newClass類);
  • ClassManager.js文件中定義了ClassManager單例,它主要負責對類的管理,如類的創建與類實例化等;
  • Loader文件中定義了Loader單例,實現了ExtJS4.0中動態加載類的功能。

image

我是用的sencha分析的,不過sencha也是基於ext的


在ExtJs4.0中,聲明類的方式改為了 Ext.define('ClassName',{}); 這個方法其實是Ext.ClassManager.create的一個別名,具體用法請看API吧,這里只談談具體的實現

分析代碼咱先從入口開始

Ext.define 在Ext.ClassManager中

 
          
   1:          /**
   2:           * Convenient shorthand for {@link Ext.ClassManager#create}, see detailed {@link Ext.Class explanation}
   3:           * @member Ext
   4:           * @method define
   5:           *    alert( Object.keys(Ext.ClassManager.classes) )
   6:           */
   7:          define: alias(Manager, 'create'),
 
         
alias(object, methodName):顧名思義,別名方法,將object的mothodName方法賦予給指定對象

實際上的處理函數就是定義在 Manager上的create方法了

在這個過程中,首先通過 Ext.Class建立原始Class,填充應用Ext.define中的配置信息,類預處理器。

   1:   return new Class(data, function() {
   2:   
   3:                  var postprocessors = Ext.Array.from(data.postprocessors || manager.getDefaultPostprocessors()),
   4:                      process = function(clsName, cls, clsData) {
   5:                          var name = postprocessors.shift();
   6:   
   7:                          if (!name) {
   8:                              manager.set(className, cls);
   9:   
  10:                              if (Ext.isFunction(createdFn)) {
  11:                                  createdFn.call(cls, cls);
  12:                              }
  13:   
  14:                              return;
  15:                          }
  16:   
  17:                          this.getPostprocessor(name).call(this, clsName, cls, clsData, process);
  18:                      };
  19:   
  20:                  process.call(manager, className, this, data);
  21:              });

在此方法內部,會先將className添加到data,之后會new一個Class並返回,所以可以說Ext.define出的類都是Class這個類的實例,這里其實是Class構造函數中的newClass類,Class實例都被Manager.classes給保存着

由此可見

ClassManager.js只是定義了ClassManager單例,它主要負責對類的管理,如類的創建與類實例化等;


真正核心的文件Class.js

   1:    Ext.Class = function(newClass, classData, createdFn) {

其實內部轉換做了幾件事:用自己的語言表述下

  1. 定義新類
  2. 拷貝base靜態方法到新的類中,就是最終的基類,在EXT3.4中最終頂層是事件Observable
  3. 預處理器(其實就是被一輪預定義的代碼給XXXX一遍)
  4. 返回newClass這個新類

其實在外部還有后處理器,這個以后再說


具體的實現咱們看源碼:

   1:          if (Ext.isObject(newClass)) {
   2:              createdFn = classData;
   3:              classData = newClass;
   4:              newClass = function() {
   5:                  return this.constructor.apply(this, arguments);
   6:              };
   7:          }

這里要這樣寫,其實這里涉及到了EXT的組件模型管理機制

EXT是一套繼承體系,

我先搬運一張3.4的圖(4.0也類似)

image

 

用我的理解就是一種倒序法,簡單的說

Extjs組件架構采用的是 一套倒樹結構,父類子類之間關系是可以通過繼承實現

還是用我的項目為例吧,反正這個東東我也實現了

new 一個Content對象

   1:   
   2:          //Activity行為預創建節點,支持PPT多動畫
   3:          if (sqlRet.imageId) {
   4:              return function(rootEle, pageIndex) {
   5:                  Xut.create('Xut.Content', {
   6:                      'container'   : rootEle || opts.rootEle,
   7:                      "type"        : 'Content',
   8:                      "id"          : sqlRet.imageId,
   9:                      "pageIndex"   : pageIndex,
  10:                      "isAutoPlay"  : false,
  11:                      "activityMode": true, //針對預先觸摸加載方式
  12:                      "processstate": "preprocess"
  13:                  })
  14:              }
  15:          }

如圖創建了一個  new Xut.Content 對象, 可是在實際構造中,代碼的開始執行確實最頂層基類Xut.Component

代碼中的實現

定義的Xut.Content 類

 
         

                              

   1:  Xut.define('Xut.Content', {                
   2:                                             
   3:      //繼承Xut.ActionBase類                 
   4:      extend: 'Xut.ActionBase',              
   5:                                             
   6:      //PPT動畫接口                          
   7:      mixins: {                              
   8:          EffectApi: 'Xut.EffectApi'         
   9:      },

 

   1:  //================ 熱點動作處理類=============
   2:  //
   3:  //  點擊動作行熱點基類
   4:  //   
   5:  //   繼承  Xut.Behavior 行為基類
   6:  //  
   7:  //   1 獲取數據
   8:  //   2 配置關閉按鈕
   9:  //
  10:  //
  11:  Xut.define('Xut.ActionBase', {
  12:   
  13:      /* 開始定義 */
  14:   
  15:      extend: 'Xut.Behavior',

 

   1:  //================ 熱點動作處理類=============
   2:  // 
   3:  //  熱點具有的基本行為動作
   4:  //      
   5:  //  1 Iscroll 導入擴展
   6:  //  
   7:  //  2 關閉按鈕生成
   8:  //   
   9:  //  3 創建關閉按鈕
  10:  //
  11:   
  12:  Xut.define('Xut.Behavior', {
  13:   
  14:      /* 開始定義 */
  15:   
  16:      extend: 'Xut.Component',

 

//==============UI交互動作基類===================
//  
//  子類  
//    觸發型熱點 ActionBase
//    交互型熱點 WidgetBase
//

Xut.define('Xut.Component', {

    /* 開始定義 */

    mixins: {
        observable: 'Xut.core.Observable'
    },

    statics: {
        AUTO_ID: 1000
    },

 

執行循序

new Xut.Content –> Xut.Component –> Xut.Behavior –> Xut.ActionBase –> Xut.Content –>

開始又往上層找 Xut-ActionBase –>Xut.Behavior->Xut.ActionBase –> Xut.Component

是不是很暈。。。ext內部就是這樣玩的,為什么要這樣,以后如果有時間說下UI組件機制就知道了

 

回歸正題,這樣的倒序調用,是怎么實現的

new一個子類,直接跨過N層到了基類Xut.Component

大家回過神來

   1:  newClass = function() {
   2:           return this.constructor.apply(this, arguments);
   3:    };

注意這里

核心點

return this.constructor.apply(this, arguments);

當我們傳遞的第一個參數不是對象(函數也是對象),那么EXT內部幫我構造了個 構造函數

這是有什么用?第二節接着分析


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM