Ext這個東東太大了,能看完就已經很不錯了,完整的源碼分析就不敢說了,大概就涉及了類管理,事件管理,數據結構緩存架構,UI組件核心機制,MVC這幾個方面,只是挑着源碼看的,沒有實際完整的使用.
公司的框架我是借鑒了EXT的結構..站在巨人的肩上我們可以走的更遠,內部的結構我已經改動了,組件的形式去架構不適合咱公司~
如圖~
- 昨天遇到個問題在mixins(向創建的類中要摻進其它類的信息)多個的時候就出問題了~ 順便就發一下我的源碼分析吧.當然是個人角度,有錯誤歡迎指出.
- 發幾本EXT的書,以前分析代碼的時候看過了,感覺還行
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中動態加載類的功能。
我是用的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) {
其實內部轉換做了幾件事:用自己的語言表述下
-
定義新類
-
拷貝base靜態方法到新的類中,就是最終的基類,在EXT3.4中最終頂層是事件Observable
-
預處理器(其實就是被一輪預定義的代碼給XXXX一遍)
-
返回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也類似)
用我的理解就是一種倒序法,簡單的說
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內部幫我構造了個 構造函數
這是有什么用?第二節接着分析