Javascript ExtJS可重用视图和控制器

Javascript ExtJS可重用视图和控制器,javascript,extjs,extjs4,reusability,Javascript,Extjs,Extjs4,Reusability,我刚从Extjs开始,基本上没有什么疑问,我创建了一个简单的视图(screenpertiespage),里面有1个select框和1个自定义视图。更改“选择框”值后,视图字段将在控制器中更新。我已经完成了创建视图和控制器的工作,它具有onchange选择框值的侦听器,并更新相关的视图字段 但现在的问题是:在我的应用程序中,我必须创建ScreenPropertiesPage视图的4个实例,当从任何视图触发onchange事件时,第一个视图的文本框总是更新。如何将事件合并到特定视图?组合控制器和视图

我刚从Extjs开始,基本上没有什么疑问,我创建了一个简单的视图(screenpertiespage),里面有1个select框和1个自定义视图。更改“选择框”值后,视图字段将在控制器中更新。我已经完成了创建视图和控制器的工作,它具有onchange选择框值的侦听器,并更新相关的视图字段

但现在的问题是:在我的应用程序中,我必须创建ScreenPropertiesPage视图的4个实例,当从任何视图触发onchange事件时,第一个视图的文本框总是更新。如何将事件合并到特定视图?组合控制器和视图并重用它的最佳过程是什么(甚至链接到我可以从中了解控制器视图重用性的文档就足够了)?非常感谢您的帮助

视图的代码框架:

Ext.define('Configurator.view.screenproperties.ScreenPropertiesPage', {
    extend: 'Ext.container.Container',
    alias: 'widget.screenpropertiespage',
    requires: [
        'Configurator.store.screenproperties.ScreenProperties'
    ],
    autoScroll: true,

    config: {
        overLayMode: false
    },
    initComponent: function () {
        var me = this;
        this.items = [{
            xtype: 'container',
            componentCls: 'screenComboSelectorPanel',
            layout: {
                type: 'hbox',
                align: 'center',
                pack: 'center'
            },
            items: [{
                xtype: 'combo',
                store: Ext.create(
                    'Configurator.store.screenproperties.ScreenProperties'
                ),
                itemId: 'screenSelector',
                margin: 3,
                width: 400,
                listConfig: {
                    maxHeight: 200
                },
                fieldLabel: 'Screen Name',
                disabledCls: 'disabledBtn',
                disabled: me.getOverLayMode(),
                queryMode: 'local',
                emptyText: '-SELECT-',
                valueField: 'screenName',
                displayField: 'screenName',
                forceSelection: true,
                selectOnTab: true,
                autoSelect: true,
                height: 25,
                tpl: Ext.create('Ext.XTemplate',
                    '<tpl for=".">',
                    '<div class="x-boundlist-item comboContainer "><div class="rowExpanedrTextArea " style="">{screenName}   </div>{[this.isExpandable(xkey,parent,values,xindex)]}</div>',
                    '</tpl>'
                ),
                displayTpl: Ext.create('Ext.XTemplate',
                    '<tpl for=".">',
                    '{screenName}',
                    '</tpl>'
                )
            }]
        }, {
            xtype: 'screenpropertieseditor',
            itemId: 'messagesEditor',
            margin: '25',
            header: true,
            frame: false,
            border: true,
            collectionName: 'messages',
            title: 'Messages'
        }]

        me.callParent(arguments);
    }
});

ScreenPropertiesPage将有更多的额外字段。我必须创建ScreenPropertiesPage的多个实例。每当任何ScreenPropertiesPage视图的组合框中的值发生更改时,都会触发Configurator.controller.ScreenProperties的screenPropertiesPageStoreHandler方法。但由于控制器中的我的ref和选择器不正确,它总是引用第一个ScreenPropertiesPage视图。

您需要知道Extjs中的
controller
singleton

但是,您可以强制
Controller
在您的情况下
ScreenProperties
处理视图的多个实例。这是通过将事件从特定视图实例触发到
控制器来完成的,以处理更复杂的逻辑

在我抛出一个示例之前,您需要知道使用
refs
处理同一视图的多个实例是错误的,因为它使用了以下代码(它只是一个包装器):
Ext.ComponentQuery.query('yourComponent')[0]所以它首先从视图实例池中获取。
因此,您需要去掉控制器中的
refs
,因为它不适用于同一视图的多个实例

好的,让我们实现这一点,并实现处理同一视图/组件的多个实例的好方法

在你看来:

initComponent: function () {
        var me = this;
        this.items = [{
            xtype: 'container',
            componentCls: 'screenComboSelectorPanel',
            layout: {
                type: 'hbox',
                align: 'center',
                pack: 'center'
            },
            items: [{
                xtype: 'combo',
                store: Ext.create(
                    'Configurator.store.screenproperties.ScreenProperties'
                ),
                itemId: 'screenSelector',
                margin: 3,
                width: 400,
                listConfig: {
                    maxHeight: 200
                },
                fieldLabel: 'Screen Name',
                disabledCls: 'disabledBtn',
                disabled: me.getOverLayMode(),
                queryMode: 'local',
                emptyText: '-SELECT-',
                valueField: 'screenName',
                displayField: 'screenName',
                forceSelection: true,
                selectOnTab: true,
                autoSelect: true,
                height: 25,
                tpl: Ext.create('Ext.XTemplate',
                    '<tpl for=".">',
                    '<div class="x-boundlist-item comboContainer "><div class="rowExpanedrTextArea " style="">{screenName}   </div>{[this.isExpandable(xkey,parent,values,xindex)]}</div>',
                    '</tpl>'
                ),
                displayTpl: Ext.create('Ext.XTemplate',
                    '<tpl for=".">',
                    '{screenName}',
                    '</tpl>'
                ),
                listeners: {
                    change: function (cmp, newValue, oldValue) {
                       this.fireEvent('onCustomChange',cmp,newValue, oldValue)
                    },
                    scope: this
                }
            }]
        }

通过这种方式,您可以使用一个控制器处理同一视图的多个实例,因为在视图中创建的每个特定组件都是通过事件传递的。

@Tarabass我刚刚编辑了问题,以获得代码片段。让我知道我的做法是否完全错误,或者我是否必须改变结构以实现可重用性。谢谢你的帮助。Glowacz非常感谢你的详细回答。一旦实现并测试它,我会将其标记为accecpted:)。为什么要在控制器的事件域中侦听视图事件?只是不使用refs,而是使用views数组('screenproperties.ScreenPropertiesPage')。从那里,您可以使用
getScreenpropertiesScreenPropertiesPageView()
?如果这适用于多个实例,那么为什么不呢。我还没试过。好吧,听起来这是一个合理的理由。在我看来,听控制器域上的查看事件似乎很奇怪:)
initComponent: function () {
        var me = this;
        this.items = [{
            xtype: 'container',
            componentCls: 'screenComboSelectorPanel',
            layout: {
                type: 'hbox',
                align: 'center',
                pack: 'center'
            },
            items: [{
                xtype: 'combo',
                store: Ext.create(
                    'Configurator.store.screenproperties.ScreenProperties'
                ),
                itemId: 'screenSelector',
                margin: 3,
                width: 400,
                listConfig: {
                    maxHeight: 200
                },
                fieldLabel: 'Screen Name',
                disabledCls: 'disabledBtn',
                disabled: me.getOverLayMode(),
                queryMode: 'local',
                emptyText: '-SELECT-',
                valueField: 'screenName',
                displayField: 'screenName',
                forceSelection: true,
                selectOnTab: true,
                autoSelect: true,
                height: 25,
                tpl: Ext.create('Ext.XTemplate',
                    '<tpl for=".">',
                    '<div class="x-boundlist-item comboContainer "><div class="rowExpanedrTextArea " style="">{screenName}   </div>{[this.isExpandable(xkey,parent,values,xindex)]}</div>',
                    '</tpl>'
                ),
                displayTpl: Ext.create('Ext.XTemplate',
                    '<tpl for=".">',
                    '{screenName}',
                    '</tpl>'
                ),
                listeners: {
                    change: function (cmp, newValue, oldValue) {
                       this.fireEvent('onCustomChange',cmp,newValue, oldValue)
                    },
                    scope: this
                }
            }]
        }
init: function (application) {
    var me = this;
    this.listen({
        // We are using Controller event domain here
        controller: {
            // This selector matches any originating Controller
            '*': {      
                onCustomChange: 'onCustonChangeHandler'
            }
        }
    });
},
onCustonChangeHandler: function(componentInstance, newValue, oldValue) {
    //Your complex logic here.
    //componentInstance is the instance of actual component in particular view
}