如何更優雅的實現ExtJS的前端MVC模式下一個App多個Controller的動態加載


尊重原創,如需轉載,請務必注明原文地址:http://www.cnblogs.com/Raoh/archive/2013/04/01/ExtJS_MVC_Controller.html

注:文中ExtJS主要指ExtJS 4.1版本,若有不當之處,煩請給予指正,謝謝!

最近有些朋友總是在問“怎么實現ExtJS的前端MVC模式下一個App多個Controller的動態加載”,也看了一些網友的實現,總的來說,我認為有必要跟大家分享一下我們目前的實現方法,所以,趁着中午休息的空閑,草擬了這篇隨筆,跟大家一起探討一下“如何更優雅的實現ExtJS的前端MVC模式下一個App多個Controller的動態加載”。

其實這也是得益於一位國外同行的啟發,具體鏈接地址已無從找起,請勿見怪!

首先,說說為什么要引入多個Controller。

ExtJS的MVC模式下,Controller默認情況下會一次性將其配置的所有store、model、自定義Ext組件,在其初始化時,一起請求下來。

這樣的實現,對於小型的項目來說,js文件較少,只使用一個Controller問題不大,但是對於大型項目來說,一次性請求那么多sotre、model、view,這是讓人無法接受的!

所以,我們有必要將不同的功能、模塊,封裝到不同的Controller中,減少其同時請求的js數量,提高用戶的體驗。

接下來,我們來了解一下,ExtJS的MVC模式下Controller的加載過程。

Ext.create('Ext.app.Application',{
    name:'XICTISD',
    appFolder:'app',
    views:['Viewport'],
    controllers:['MainController','UserController','RoleController']
});

先舉一段代碼為例,如上所示,給Ext.app.Application實例配置了三個Controller。

實際上,Ext.app.Application的構造函數中,會給它的實例添加一個屬性:controllers,這是一個Ext.util.MixedCollection()實例,其源碼如下:

me.controllers = new Ext.util.MixedCollection();

(注意:了解這一點細節,對我們后面很有幫助。)

緊接着,Ext.app.Application的構造函數中會遍歷我們給這個實例配置的三個Controller,調用當前實例的getController方法,獲取對應的Controler實例,並執行該Controller實例的init()方法,源碼如下:

for (i = 0; i < ln; i++) {
     controller = me.getController(controllers[i]);
     controller.init(me);
}

getControler方法負責返回一個Controller實例,如果參數中的Controller已經加載過,則直接取得該Controller實例並返回,如果參數中的Controller尚未加載過,則向后台發起一個請求,獲取一個Controller實例,並將這個Controler實例添加到Ext.app.Application實例的controllers里,最終返回這個Controller實例,其源碼如下:

getController: function(name) {
        var controller = this.controllers.get(name);

        if (!controller) {
            controller = Ext.create(this.getModuleClassName(name, 'controller'), {
                application: this,
                id: name
            });

            this.controllers.add(controller);
        }

        return controller;
}

到此,我們基本上清楚了Controller的加載過程,接下來,我們談談如何在一個App中動態加載多個Controller。
由於Ext.app.Application實例的controllers屬性是個Ext.util.MixedCollection()實例,因此,我們可以為其添加一個事件監聽,當有新的Controller被動態加載進來的時候,就執行這個Controller的init()方法,這能省去我們每次都手動去調用Controller的init()方法的工作,示例代碼如下:

var application;
Ext.Loader.setConfig({enabled:true});

Ext.require('Ext.app.Application',function(){
Ext.app.Application.addMembers({
    //加載Controller后觸發事件
    newControllerAdded:function(idx,cntr){
        cntr.init(this);
    },
    //判斷是否已加載指定Controller,返回Boolean
    hasController:function(name){
        return !!this.controllers.get(name);
    },
    //加載並返回指定Controller
    addController:function(name){
        return this.getController(name);
    }
});
});

Ext.onReady(function(){
 application=Ext.create('Ext.app.Application',{
    name:'MyApp',
    appFolder:'app',
    views:['Viewport'],
    controllers:['MainController'],
    launch:function(){
        Ext.tip.QuickTipManager.init();
        this.controllers.addListener('add',this.newControllerAdded,this);
        Ext.create('Ext.container.Viewport',{
            layout:'border',
            items:[{
                xtype:'mainNorth'
            },{
                xtype:'mainSouth'
            },{
                xtype:'mainWest'
            },{
                xtype:'mainCenter'
            }]
        });
        
    }
 });
});

如上代碼,我們順便為Ext.app.Application擴展了兩個方法:hasController、addController,為后續編寫代碼提供一些友好的支持,其具體用途可見代碼中的注釋。
接下來,我們就可以在需要的地方,進行動態加載Controller了,示例如下:

if(!app.hasController('SysController')){
           app.addController('SysController');
}

對於SysController中的store、model、view,只需保持原先的寫法,不需要任何更改,在調用app.addController時,會自動加載。

再也不需要你去手工調用Controller的init()方法了,代碼就這么簡單!

注:本文討論的話題僅僅是在一個app中如何動態加載多個Controller,而對於Controller中所包含的store、model、view等的動態加載,可能需要再另起一篇來進行討論,大家有興趣的話可以翻一下Ext.application.Controller源碼中的getStore()、getModel()、getView()等方法的源碼,也許能得到一些相應的提示和靈感!

 

 


免責聲明!

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



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