为什么ExtJS'items'属性的行为类似于static?

时间:2016-09-01 13:53:24

标签: javascript extjs extjs4.2

每当我拨打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');
    }
});

1 个答案:

答案 0 :(得分:0)

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

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

因此,如果在原型上定义items数组,则所有实例都指向相同的items数组。

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

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

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

我会做什么:

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

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