ExtJS从主控制器加载子控制器

时间:2013-08-27 20:26:19

标签: model-view-controller extjs extjs4

我正在开发具有多个模块的应用程序。每个模块由一个控制器,模块/存储和许多使用这些存储的视图组成。所以我决定创建主控制器和一个导航视图。当用户更改应用程序部分时,将加载相应的控制器。

这是我的主控制器的源代码:

Ext.define('My.controller.Navigation', {
extend: 'Ext.app.Controller',
views: ['layout.Navbar'],
_loadedControllers: [],
init: function() {
    var me = this;
    me.control({
        'navbar > tabpanel': {
            tabchange: me.handleNavChange
        }
    });
},
handleNavChange: function(tabPanel, newCard, oldCard, eOpts) {
    var app = My.getApplication(),
        container = app.getContainerPanel(),
        components = Ext.ComponentQuery.query('viewport > panel > panel:not([cls~=bpte-layout])'),
        name = this.formatControllerName(newCard.itemId),
        i=0;
    //Remove initialized widgets:
    for(; i < components.length; i++) {
        container.remove( components[i], true );
    }
    //Load and initialize controller:
    controller = app.getController(name);
    if(this.isControllerLoaded(name))
        controller.init();
    this.addLoadedController(name);
},
formatControllerName: function(id) {
    return id.charAt(0).toUpperCase() + id.substr(1).toLowerCase();
},
isControllerLoaded: function(name) {
    for(var i=0; i < this._loadedControllers.length; i++) {
        if(this._loadedControllers[i] == name)
            return true;
    }
    return false;
},
addLoadedController: function(name) {
    this._loadedControllers.push(name);
}});

这是我的控制器的抽象源代码:

Ext.define('My.controller.ControllerX', {
    extend: 'Ext.app.Controller',
    stores: ['Store#1','Store#2'],
    views:  ['Widget#1','Widget#2','Widget#3'],
    init: function() {
        var container = My.getApplication().getContainerPanel();
        container.add( Ext.widget('Widget#1') );
        container.add( Ext.widget('Widget#2') );
        this.control({ ... });
        ...
    }
    ...
});

第一次加载子控制器时,一切正常。但是当我再次导航到同一个子控制器时,我遇到了Stores的问题。商店就像复制一样。例如,当我在商店中添加新模型然后同步商店时,它会添加两个模型而不是一个模型,并将它们发送到服务器。

我做错了什么?

2 个答案:

答案 0 :(得分:0)

Controller.init只能被召唤一次。将log置于动态加载的控制器init方法中,可能会多次调用它。

答案 1 :(得分:0)

好的,我为我解决了这个问题。我已经更新了我的主控制器,它在删除时不会破坏视图,它将它们存储在相应的变量中,并在我们导航到已经加载的部分时使用这些视图。

Ext.define('My.controller.Navigation', {
extend: 'Ext.app.Controller',
views: ['layout.Navbar'],
_loadedControllers: {},
init: function() {
    var me = this;
    me.control({
        'navbar > tabpanel': {
            tabchange: me.handleNavChange
        }
    });
},
handleNavChange: function(tabPanel, newCard, oldCard, eOpts) {
    var app = My.getApplication(),
        container = app.getContainerPanel(),
        components = Ext.ComponentQuery.query('viewport > panel > panel:not([cls~=bpte-layout])'),
        currentController = this.formatControllerName(oldCard.itemId),
        newController = this.formatControllerName(newCard.itemId),
        i=0;
    //Store old components and remove them from container:
    this._loadedControllers[currentController] = components;
    for(; i < components.length; i++) {
        container.remove( components[i], false );
    }
    if(this.isControllerLoaded(newController)) {
        //Restore widgets of already loaded controller:
        for(i=0; i < this._loadedControllers[newController].length; i++) {
            container.add(this._loadedControllers[newController][i]);
        }
    } else {
        //Load new controller:
        app.getController(newController);
    }
},
formatControllerName: function(id) {
    return id.charAt(0).toUpperCase() + id.substr(1).toLowerCase();
},
isControllerLoaded: function(name) {
    for(var key in this._loadedControllers) {
        if(!this._loadedControllers.hasOwnProperty(key))
            continue;
        if(key == name)
            return true;
    }
    return false;
}});

此外,应用程序变得更快,因为每次进入该部分时都不会重建窗口小部件(视图)。