7

我正在尝试编写一个可重用的项目选择面板,其中用户有一个网格,其中包含他可以选择的项目和一个可以用来过滤网格内容的小文本字段。现在(简化的)视图代码看起来像这样并且可以工作

Ext.define('MyApp.view.items.ItemSelectorPanel', {
    extend: 'Ext.panel.Panel',
    require: 'MyApp.view.items.SimpleItemGrid',
    alias: 'widget.ItemSelectorPanel',
    layout: 'form',

    config: {
        itemStore: false
    },

    constructor: function(config) {
        this.initConfig(config);

        this.superclass.constructor.call(this, config);

        this.add([
            {
                fieldLabel: 'Filter',
                name: 'filter'
            },
            {
                xtype: 'SimpleItemGrid',
                collapsible: true,
                store: this.getItemStore()
            }
        ]);

        return this;
    }
});

如您所见,ItemSelectorPanel使用该config属性来公开一个接口,调用站点可以在该接口中指定要使用的项目商店。

调用站点(在这种情况下,面板被添加到 TabPanel):

var panelToAdd = {
    xtype: 'panel',
    title: 'New Selection',
    closable: true,
    padding: 10,
    items: [{
        title: 'Select node',
        xtype: 'ItemSelectorPanel',
        itemStore: itemStore
    }]
};

现在,我喜欢 ExtJS 4 的声明式风格以及它如何帮助遵循 MVC 模式。我希望视图中的代码量尽可能少。不幸的是,这不起作用

Ext.define('MyApp.view.items.ItemSelectorPanel', {
    /* ... same as above ... */

    constructor: function(config) {
        this.initConfig(config);

        this.superclass.constructor.call(this, config);

        return this;
    },

    items: [
            {
                fieldLabel: 'Filter',
                name: 'filter'
            },
            {
                xtype: 'SimpleItemGrid',
                collapsible: true,
                store: this.getItemStore   // <-- interesting part
            }
    ]
});

config有没有办法通过父属性的属性以声明方式公开嵌套/子组件的配置?

4

4 回答 4

6

首先是一般情况

除非您确切知道自己要做什么,否则切勿在类定义中的函数之外添加对象。因为如果你这样做,所有实例都将共享该对象的同一个实例。我想我不需要提及这会导致...

如果您需要在那里放置一个对象,您应该在构造函数中克隆它。

到你的代码

我不知道是什么this.initConfig(config);,但config变量不是你的类中的那个,它是构造函数参数中的那个。我建议您也使用initComponent()初始化而不是constructor()使用构造函数,除非您明确需要使用构造函数,在您的情况下,您似乎没有。

'config' 也不会被转发,因为它不会被执行 up->bottom 而是bottom->up ,其中配置获取的手和所有其他属性(已经)被继承。

我仍然不完全知道你的目标是什么,因此我不能给你任何建议你应该如何做到这一点,但我可以肯定地说你这样做的方式会导致问题。

编辑

我仍然不确定我是否完全理解您的需求,但以下应该可以工作(如果您也需要听众,您可以看看Ext.util.Bindablemixin)

Ext.define('MyApp.view.items.ItemSelectorPanel', {
    extend: 'Ext.panel.Panel',
    require: 'MyApp.view.items.SimpleItemGrid',
    alias: 'widget.ItemSelectorPanel',
    layout: 'form',

    initComponent: function() {
        // Initialize the store (might be a instance or a storeId)
        var store;
        if (this.itemStore) {
            store = Ext.data.StoreManager.lookup(store);
        }
        this.itemStore = store || null;
        // Add is not valid (at least not before the parent inits are executed)
        this.items = [{
            fieldLabel: 'Filter',
            name: 'filter'
        }, {
            xtype: 'SimpleItemGrid',
            collapsible: true,
            store: this.getItemStore()
        }];

        this.callParent(arguments);
    },

    getItemStore: function() {
        return this.itemStore;
    }
});
于 2013-01-18T10:49:41.610 回答
2

不,您不能按照您描述的方式进行操作。原因很简单,我们举个例子:

Ext.define('MyClass', {
    someProp: this.foo(),

    foo: function(){
        return bar;
    }
});

在这里,我们调用 define() 方法,并将一个对象作为配置传递给它。因此,整个对象(包括对 foo() 的调用)在它被传递给定义之前就被评估了,所以类/方法在那个时候甚至不存在。

即使您可以这样做,这也是 foo 是类上的实例方法的复杂性,但是您尝试调用它的方式就好像它是静态方法一样。

所以,答案是,你需要使用某种方法来做到这一点,initComponent 通常比构造函数更受欢迎。

于 2013-01-18T10:59:45.443 回答
1

我没有看到解决原始问题的答案。这是我发现的工作......

创建一个 myClass 的实例,传入一个值为 'bar' 的配置 'foo'

var myClassInstance = Ext.create('MyApp.view.myClass', {
    foo: 'bar'
});

myClass 定义如下:

Ext.define('MyApp.view.myClass', {
extend: 'Ext.container.Container',
alias: 'widget.myclass',

config: {
    foo: 'defaultVal'
},

constructor: function(configs) {
    this.callParent(arguments);  //create class, calls initComponent

    var try1 = getFoo(); //try1 is 'defaultVal'
    this.initConfig(configs);  //initializes configs passed in constructor
    var try2 = getFoo(); //try2 is 'bar' 
},

initComponent: function() {
    //myClass declaration here ...

    this.callParent();
}
于 2013-08-10T23:52:09.550 回答
1

您可以在类的声明中定义项目,但在声明时不能从类中调用任何方法。为了解决这个问题,只定义没有商店的项目,而不是使用 initComponent 方法为您的视图设置商店。

于 2013-01-18T11:09:56.530 回答