为什么 ExtJS 'items' 属性 表现得像静态的?

Why ExtJS 'items' property behaves like static?

每次调用 Ext.create() 时,新按钮都会推送到表单。但是counter还是离开了== 1

如果我删除 items: [] 并取消注释 Ext.apply(/*...*/) 一切正常。

为什么 items 属性 表现得像静态的?

Ext.application({
    name : 'Fiddle',

    launch : function() {
        Ext.define('TestForm', {
            extend: 'Ext.form.Panel',
            title: 'TestForm',
            margin: 40,
            items: [], // remove it
            counter: 100,
            initComponent: function() {
                this.counter++;
                /*Ext.applyIf(this, {
                    items: []
                });*/
                this.items.push({ xtype: 'button', text: 'test'+this.counter})
                this.callParent(arguments);
            },
            renderTo: Ext.getBody()
        })

        Ext.create('TestForm');
        Ext.create('TestForm');
        Ext.create('TestForm');
    }
});

当组件派生自原型时,所有成员都会被传递 - 一些通过引用,一些通过值,具体取决于类型。

  • 计数器是一个int,按值传递。
  • Items 是一个数组,通过引用传递。

因此,如果您在原型上定义 items 数组,所有实例都指向同一个 items 数组。

由于您将按钮配置添加到该数组(其中有两个引用,一个来自原型,一个来自实例),每次您创建一个新实例时,都会向该数组添加一个新按钮,保留旧的。

之后,在 callParent 中,ExtJS 迭代项目 属性(然后是一个数组)并从数组内容创建一个组件的 MixedCollection。然后将 mixedCollection 存储在项目 属性 中。在此期间,引用中断 - 这就是为什么第一个实例没有将第二个按钮放入其项目中的原因。

为确保您不会 运行 陷入这些问题,有一种可能: 永远不要将引用传递类型定义为原型的成员。

我会做什么:

    Ext.define('TestForm', {
        extend: 'Ext.form.Panel',
        title: 'TestForm',
        margin: 40,
        counter: 100,
        initComponent: function() {
            this.counter++;
            Ext.apply(this, {
                items: [{ xtype: 'button', text: 'test'+this.counter}]
            });
            this.callParent(arguments);
        },
        renderTo: Ext.getBody()
    })

    Ext.define('TestForm', {
        extend: 'Ext.form.Panel',
        title: 'TestForm',
        margin: 40,
        counter: 100,
        initComponent: function() {
            this.counter++;
            this.callParent(arguments);
            this.add({xtype: 'button', text: 'test'+this.counter});
        },
        renderTo: Ext.getBody()
    })

第一个在实例化组件之前将项目定义添加到每个实例,另一个在组件实例化之后将按钮添加到布局。