ExtJS - 如何将组件配置选项传递给XTemplates?

时间:2015-11-13 12:04:10

标签: extjs extjs6

我定义了一个扩展Ext.view.View的以下类:

Ext.define('Aft.view.comments.CommentsList', {
  extend: 'Ext.view.View',
  xtype: 'comments-list',

  parameter: false,

  tpl: new Ext.XTemplate(
    '<tpl for=".">',
    '  <div class="comment">',
           // some code here
    '    <div class="fault">',
    '      <tpl if="this.parameter">',
             // some code also here         
    '      </tpl>',
    '    </div>',
    '  </div>',
    '</tpl>',
    {
      strict: true,
      // other methods and fields
    }),

  initComponent: function() {
    this.config = Ext.apply({}, this.config);
    this.tpl.config.parameter = this.config.parameter;
    this.callParent(arguments);
  }
});

正如你所看到的,我试图将一个布尔参数从组件外部传递给它内部的XTemplate。我试图这样做,因为该组件在3个不同的地方使用。在其中一个中,我希望它看起来略有不同(只是没有一个div)。我发现参数化的XTemplate是一个很好的解决方案,但我不能强迫它工作。我正在创建这样的组件:

items: [
    {
        xtype: 'comments-list',
        parameter: false
    }
]

无论我作为参数放置什么,我在配置中放置的所有内容似乎都在我的自定义类的其他实例之间共享。因此,要么每个CommentsList都将参数设置为true,要么将每个都设置为false。我显然错过了一些东西,但似乎这个话题也给别人造成了困惑。尽管我没有找到解决这个问题的正确方法。我已经在类定义中尝试了与config,factoryConfig和变量的各种组合,但似乎没有任何效果。

因此,我非常感谢解决方案,或者至少是博客文章或文档的宝贵链接。非常感谢你提前。

如果这是相关的,我使用的是ExtJS 6 classic。

1 个答案:

答案 0 :(得分:4)

原因是您的tpl位于prototype and is therefore shared between instances。这是我对Ext在原型上设置对象的方式的最大宠儿,而不了解它的真正含义。这也意味着如果您需要,您将无法访问this,因为您在我的示例中会看到,因为您需要传递&#34;传递&#34;配置到模板中。

你提出的一个很好的问题实际上是给我一个很好的简化例子,证明了我总是试图给我的团队做点(因为它是yui-ext而一直在开发Ext-JS);

您的tpl对象正在Aft.view.comments.CommentsList.prototype上设置,因此正在共享。

正确的解决方案是从构造函数(或tpl)初始化initComponent,以便为每个实例创建一个新模板。见https://fiddle.sencha.com/#fiddle/111v

Ext.define('Aft.view.comments.CommentsList', {
  extend: 'Ext.view.View',
  xtype: 'comments-list',

  // Primitives are always OK on prototypes because if you write, you will
  // modify a property on the instance, not the prototype
  parameter: false, 

  initComponent: function() {
    this.tpl = new Ext.XTemplate(
    '<tpl for=".">',
    '  <div class="comment">',
           // some code here
    '    <div class="fault">',
    '      <tpl if="this.parameter">',
             // some code also here         
    '      </tpl>',
    '    </div>',
    '  </div>',
    '</tpl>',
    {
      strict: true,
      parameter: this.parameter
    });
    this.callParent(arguments);
  }
});

Ext Prototype Rant

在原型上设置内容时,这意味着调用者在传入配置对象时仍然可以覆盖它。例如,在上面的类中,我可以在实例化时覆盖tpl(并打破类的功能)。

// Will likely break the class if we have some assumptions in the HTML about the code
items: [{xtype: 'comments-list', tpl: '<div>Broke you</div>'}]

如果您在initComponent内定义它,您将覆盖用户传入的任何内容。明智地使用它。如果你在原型上定义它,它只是一个默认值,你的代码不应该依赖它。

显然,我们仍然需要记住原型上的对象是共享的,所以如果你想要一个不共享的默认对象,你应该使用

initComponent: function() {
   Ext.applyIf(this, {
      someProp: {defaultObject: true}
   });
   this.callParent();
}

最后,如果你有一个没有改变的对象(默认值),那么它并不重要,最好存储在原型上以节省内存,但你必须要小心你不要修改它(除非你可以使用Object.freeze)。