【问题标题】:ExtJS: How to create own Class with other ExtJS components?ExtJS:如何使用其他 ExtJS 组件创建自己的类?
【发布时间】:2014-07-29 12:37:47
【问题描述】:

我正在尝试使用不同的项目创建 Panel 类对象。基本上它与 ExtJS 中的桌面应用程序有关。
DetailView.js

Ext.define("App.view.DetailView", {
   extend : 'Ext.panel.Panel',
   alias : 'widget.asset-panel',
   itemId : 'Detail-view',
   region : 'center',
   initComponent : function() {
      this.items = [ comboboxes, customPanel ];
      this.callParent(arguments);
   }
});  

我正在尝试以两种方式创建items 组件,即使用xtype 和使用Ext.create() 方式。我不确定哪个是正确的,我应该如何解决。下面是 DetailView.js

中的comboboxes 变量
var comboboxes = {
xtype : 'form',
border : false,
padding : '5 5 5 5',
items : [ {
    layout : 'column',
    border : false,
    width : 600,
    items : [ {
        xtype : 'combobox',
        columnWidth : .15,
        itemId : 'filter-1',
        store : [ 'Employee', 'Manager', 'TeamLead' ]
    }, {
        xtype : 'combobox',
        columnWidth : .15,
        margin : '0, 0, 0, 15',
        store : [ 'Keywords', 'Names' ]
    }, {
        xtype : 'combobox',
        columnWidth : .15,
        margin : '0, 0, 0, 15',
        store : [ 'Some Data here' ]
    }]
} ]
};  

到目前为止一切顺利,如果我将 this.items = [comboboxes] 保留在 DetailView 类中,它可以正常工作,没有任何问题。但是当我尝试添加其他组件时,例如 DetailView.js

中的 customPanel
var custom = Ext.create('Ext.panel.Panel', {
itemId : 'panel_1',
height : 300,
border : false,
layout : 'card',
items : [ {
    xtype : 'container',
    itemId : 'listCt',
    layout : {
        type : 'vbox',
        align : 'stretch'
    },
    defaults : {
        margin : 2
    },
    items : []
}, {
    xtype : 'container',
    itemId : 'fitCt',
    layout : 'fit'
} ]
});  

我尝试了两种初始化面板的方法,如上和使用initComponent(),但每次都会出错:

Uncaught TypeError: Cannot set property 'component' of null ext-all.js:22
Ext.cmd.derive.privates.finishRender ext-all.js:22
Ext.cmd.derive.finishRenderItems ext-all.js:22
Ext.cmd.derive.finishRender ext-all.js:22
Ext.cmd.derive.privates.finishRenderChildren ext-all.js:22
Ext.cmd.derive.afterRender ext-all.js:22
Ext.cmd.derive.privates.finishRender ext-all.js:22
Ext.cmd.derive.finishRenderItems ext-all.js:22
Ext.cmd.derive.finishRender ext-all.js:22
Ext.cmd.derive.privates.finishRenderChildren ext-all.js:22
Ext.cmd.derive.afterRender ext-all.js:22
Ext.cmd.derive.privates.finishRender ext-all.js:22
Ext.cmd.derive.finishRenderItems ext-all.js:22
Ext.cmd.derive.finishRender ext-all.js:22
Ext.cmd.derive.privates.finishRenderChildren ext-all.js:22
Ext.cmd.derive.afterRender ext-all.js:22
Ext.cmd.derive.afterRender ext-all.js:22
Ext.cmd.derive.privates.finishRender ext-all.js:22
Ext.cmd.derive.render ext-all.js:22
Ext.cmd.derive.privates.doAutoRender ext-all.js:22
Ext.cmd.derive.show ext-all.js:22
Ext.define.restoreWindow Desktop.js?_dc=1406637300888:388
Ext.define.onShortcutItemClick Desktop.js?_dc=1406637300888:199
fire ext-all.js:22
doFireEvent ext-all.js:22
a.doFireEvent ext-all.js:22
fireEventArgs ext-all.js:22
fireEvent ext-all.js:22
Ext.cmd.derive.processUIEvent ext-all.js:22
Ext.cmd.derive.handleEvent ext-all.js:22
Ext.cmd.derive.doFire ext-all.js:22
Ext.cmd.derive.fire ext-all.js:22
Ext.cmd.derive.doDispatchEvent ext-all.js:22
Ext.cmd.derive.dispatch ext-all.js:22
Ext.cmd.derive.dispatch ext-all.js:22
Ext.cmd.derive.doPublish ext-all.js:22
Ext.cmd.derive.publish ext-all.js:22
Ext.cmd.derive.onDelegatedEvent ext-all.js:22
(anonymous function)  

重新初始化窗口时出错。即它仅在第一次执行时起作用,但在第二次执行时不起作用。我怀疑组件是否被正确渲染和销毁。可能的原因是什么?任何可能的解决方案?

【问题讨论】:

    标签: javascript extjs extjs5


    【解决方案1】:

    您似乎在将组件销毁后重新使用它们:

    initComponent : function() {
        // comboboxes & customPanel will be the same instances 
        // for every App.view.DetailView you create
        this.items = [ comboboxes, customPanel ];
        this.callParent(arguments);
    }
    

    这里也一样:

    items : [{
        xtype : 'container',
        itemId : 'listCt',
        // ...
    
        // The component in this items variable will be destroyed when their
        // parent is destroyed, and won't be usable again after that
        items : items
    
        // ...
    }]
    

    您有两种可靠的方法来定义带有预设项的自定义类。

    首先,您可以使用内联 (xtype) 配置。这具有延迟初始化的优点;此外,每次您创建自定义组件的实例时,Ext 都会创建项目的单独实例。

    例如:

    Ext.define('My.Panel', {
        extend: 'Ext.panel.Panel'
    
        ,items: [{
            xtype: 'textfield'
            ,fieldLabel: "My field"
        },{
            xtype: 'component'
            ,html: "Bla bla bla"
        }]
    });
    
    var myFirstPanel = new My.Panel({
        renderTo: Ext.getBody()
        ,title: "First Panel"
    });
    
    var mySecondPanel = new My.Panel({
        renderTo: Ext.getBody()
        ,title: "Second Panel"
    });
    

    如果您需要更多参与的处理,请使用 initComponent 方法,但请务必在其中创建子项的新实例。

    Ext.define('My.InitComponentPanel', {
        extend: 'Ext.panel.Panel'
    
        ,customFieldLabel: "Example field"
    
        ,initComponent: function() {
    
            // initComponent will be called each time a InitComponentPanel
            // is created, and a new textfield will be created for each
    
            this.items = [
                new Ext.form.field.Text({
                    fieldLabel: this.customFieldLabel
                });
            ];
    
            this.callParent(arguments);
        }
    });
    
    var panel1 = new My.InitComponentPanel({
        renderTo: Ext.getBody()
        ,customFieldLabel: "First field"
    });
    
    // will destroy panel1's items, but no problem
    panel1.destroy();
    
    var panel2 = new My.InitComponentPanel({
        renderTo: Ext.getBody()
        ,customFieldLabel: "Second field"
    });
    

    如果您直接使用 Ext 组件(不扩展它们)也是如此;不要在多个地方使用现有组件。

    // Inline (uninstantiated) items are always fine
    var panel = new Ext.panel.Panel({
        renderTo: Ext.getBody()
        ,items: [{
            xtype: 'checkbox'
            ,boxLabel: "My checkbox"
        }]
    });
    
    // You can also create children beforehand
    var checkbox = new Ext.form.field.Checkbox;
    var panel2 = new Ext.panel.Panel({
        renderTo: Ext.getBody()
        ,items: [checkbox]
    });
    
    // But don't reuse the checkbox for another panel
    var panel3 = new Ext.panel.Panel({
        renderTo: Ext.getBody()
        // this will remove the unique checkbox instance from panel2
        // and if panel2 has been destroyed meanwhile, it will crash
        ,items: [checkbox]
    });
    

    不要忘记,您还可以从已使用 addinsertremove 等方法创建的容器中添加/删除项目(但不要触摸 items直接属性!)。

    【讨论】:

    • 哦,伙计!所以如果我们定义我们的类说Ext.define("My.CustomPanel",{...})所以每次销毁后重用这个组件我必须使用new关键字重新初始化它! ? (因为它是一个桌面应用程序,所以一旦我关闭应用程序中的Ext.window.Window 实例,我必须更频繁地重复使用它们)
    • 是的,您必须为每个需要它的地方创建一个组件实例,并且必须在它们被销毁后创建新的。使用new 关键字,或Ext.create,它们大致相当,或者在某些容器的配置中使用组件的xtype(或Ext5/Touch 中的xclass)。然而,可以做的是移动一个现有的组件实例,将它添加到另一个容器中;如果你在销毁第一个容器之前这样做,它会起作用。
    • 您也可以查看autoDestroy 选项,但我不会费心自己管理组件生命周期(从那时起,您必须自己销毁子组件以防止内存泄漏).. .
    • 它总有一天会杀了我.. 什么以及如何理解这一切?我正在尝试在 extjs apidoc 上阅读它,但到目前为止它对我来说并没有那么好闻。顺便说一句,非常感谢你向我解释这个
    • 很抱歉,我真的不知道您在哪里可以找到有关此的文档,您可以通过经验获得这些文档...我写过关于 initComponent in another question 的文章,它可能会有所帮助。但是 Ext 的生命周期并没有那么复杂,如果你不把框架包装得太多,它本质上是自动的(感谢autoDestroy)。
    猜你喜欢
    • 1970-01-01
    • 2011-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-22
    • 1970-01-01
    相关资源
    最近更新 更多