【问题标题】:In ExtJS components how to forward config: {} items to sub components在 ExtJS 组件中如何将 config: {} 项转发到子组件
【发布时间】:2023-03-28 11:04:01
【问题描述】:

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

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 属性以声明方式公开嵌套/子组件的配置?

【问题讨论】:

标签: extjs model-view-controller extjs4 extjs4.1 extjs4.2


【解决方案1】:

首先是一般性

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

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

到你的代码

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

此外,“配置”没有被转发,因为它没有被执行向上->底部但底部->向上执行配置,并且所有其他属性(已经)被继承。

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

编辑

我仍然不确定我是否完全了解您的需求,但以下应该可以工作(如果您也需要侦听器,您可以查看 Ext.util.Bindable mixin)

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;
    }
});

【讨论】:

  • 原始提问者发布的内容是有效的,extjs 网站上的示例显示了完全相同的初始化方法。当您在涉及标准 initConfig 函数的类级别创建名为“config”的对象时,有一种特殊情况。不过适合他这里的情况吗..?不。他真的应该按照你的描述去做。
  • @Reimius 绝对!但据我所知,这只是在您定义“超类”时。至少这是我曾经使用过的唯一情况。还是我错了?
  • @sra 看看这里link。他们采用 cfg 构造函数参数(不是 config 变量,正如您还指出的那样)并将其放入 initConfig() 调用中。我想要实现的是将 SimpleItemGrid 的“存储”属性呈现给调用者,使其看起来好像是 ItemSelectorPanel 的属性。我希望对外界隐藏 ItemSelectorPanel 的内部细节。
  • @ErosC 它们都是超类,您无需访问这些核心属性即可归档您的目标。查看我的编辑
【解决方案2】:

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

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

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

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

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

所以,答案是,您需要使用某种方法来执行此操作,initComponent 通常比构造函数更受欢迎。

【讨论】:

  • 整个配置属性处理似乎以某种方式与构造函数相关联。我尝试将其移至 initComponent 但出现错误。 documentation 也将其放入构造函数中。
【解决方案3】:

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

【讨论】:

  • 你能举个例子吗?我试过` initComponent: function () { Ext.getCmp('abcd').reconfigure(this.getItemStore()); }, items: [ { fieldLabel: 'Filter', name: 'filter' }, { xtype: 'SimpleItemGrid', itemId: 'abcd', collapsible: true } ] ` 告诉我我在 undefined 上调用 reconfigure()。
【解决方案4】:

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

创建一个 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();
}

【讨论】:

    猜你喜欢
    • 2015-04-02
    • 1970-01-01
    • 2018-01-12
    • 2021-08-24
    • 2017-07-25
    • 2019-04-11
    • 1970-01-01
    • 2021-05-13
    • 1970-01-01
    相关资源
    最近更新 更多