ExtJs 5上的Global View + ViewController

时间:2015-04-22 20:33:04

标签: extjs mvvm extjs5

我想要实现的非常简单,我希望在我的应用程序中拥有一个主菜单,并为所有视图提供相同的功能。

我想创建一个只包含菜单部分加上自己的viewcontroller的视图。实现这一目标的最佳方式是什么?

我正在使用ExtJS 5实现MVVM范例。

谢谢!

2 个答案:

答案 0 :(得分:3)

这是一个非常广泛的问题,关于如何在不了解应用程序的其他部分的情况下构建非常难以回答的应用程序。

通常,任何应用程序全局(不是应用程序容器/视口)都可能最容易用MVC实现。菜单控制器(MVC控制器)将监听菜单事件,然后它将向下钻取组件层次结构以调用组件的API方法来执行操作。

如果我知道应用程序,我可以更具体。

答案 1 :(得分:2)

我会创建一个主视图,在其中定义应用程序的固定部分,以及一个具有布局' fit'持有不断变化的观点"。而不是布局'适合',这也可以是标签面板或其他东西。当然,没有什么可以阻止您使用视图控制器向此主视图的固定部分添加行为。

事实上很简单。然后,您可以通过将当前应用视图放入主视图的中央容器来更改它。您需要某种决策逻辑和配置数据来定义应用程序中的可用视图。这可能最好将它包装在专用于此任务的单个位置,即app控制器(而不是视图控制器)。

这里是example fiddle,下面是解释代码不同部分的原因:

所以,你从这样的观点开始:

Ext.define('My.view.Main', {
    extend: 'Ext.container.Container',

    xtype: 'main', // you can do that in ext5 (like in touch)
    // shortcut for that:
    //alias: 'widget.main',

    controller: 'main',

    layout: 'border',

    items: [{
        xtype: 'panel',
        region: 'west',
        layout: {type: 'vbox', align: 'stretch', padding: 5},
        defaults: {
            margin: 5
        },
        items: [{
            xtype: 'button',
            text: "Say Hello",
            handler: 'sayHello'
        }]
    },{
        // target for app's current view (that may change)
        xtype: 'container',
        region: 'center',
        layout: 'fit'
    }]
});

Ext.define('My.view.MainController', {
    extend: 'Ext.app.ViewController',

    alias: 'controller.main',

    sayHello: function() {
        Ext.Msg.alert("Controller says:", "Hello :-)");
    }
});

然后,将此主视图设置为"视口"你的申请。我还添加了一种方法来更改中心视图。我认为Application实例是一个很好的地方,但您可以将此方法移动到另一个专用的app控制器......

Ext.application({
    name : 'My', // app namespace

    // in real life, Main view class would lie in another file,
    // so you need to require it
    views: ['Main'],

    // from ext 5.1, this is the config to auto create main view
    mainView: 'My.view.Main',

    // we also register a ref for easy retrieval of the main view
    // (the value 'main' is the xtype of the main view -- this is
    // a component query)
    refs: {
        main: 'main'
    },

    setCenterRegion: function(cmp) {
        // getter generated by refs config
        // you could another layout in the main view, and another component query of course
        var center = this.getMain().down('[region=center]');
        // replace the current center component with the one provided
        center.removeAll();
        center.add(cmp);
    }
});

所以,现在,您可以使用以下代码更改视图:

My.getApplication().setCenterRegion(myView);

您可以通过主视图的ViewController连接它,并在视图中将其用作处理程序。例如,在ViewController中:

changeView: function() {
    // retrieve the next view, this is application specific obviously
    var myView = ...

    // My.getApplication() gives you the instance created by
    // Ext.getApplication in namespace 'My'
    My.getApplication().setCenterRegion(myView);
}

并且,在主视图中,使用如下项目:

{
    xtype: 'button',
    text: "Change view (by view controller)",
    handler: 'changeView'
}

这对于简单的应用程序来说可能没什么问题,但这看起来似乎是混合的关注点。决定应用程序级别视图交换似乎更像是应用程序控制器的业务。因此,我宁愿建议将changeView方法放在app控制器中,并使用组件查询将其公开给组件,如下所示:

Ext.define('My.controller.Main', {
    extend: 'Ext.app.Controller',

    config: {
        control: {
            // components will have to match this component query
            // to be animated with the change view behaviour
            '#changeView': {
                click: 'changeView'
            }
        }
    },    

    changeView: function() {
        My.getApplication().setCenterRegion(/*
            ...
        */);
    }
});

您可以将行为挂钩到任何视图中的组件,如下所示:

{
    xtype: 'button',
    text: "Change view (by app controller)",
    // will be matched by the controller component query
    itemId: 'changeView'
}