ExtJS - 如何将组件配置选项传递给 XTemplates?
ExtJS - How to pass Component config options to XTemplates?
我定义了以下 class 扩展 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
}
]
而且不管我输入什么作为参数,我在配置中输入的所有内容似乎都在我的自定义 class 的其他实例之间共享。因此,要么每个 CommentsList 都将参数设置为 true,要么每个都将其设置为 false。我显然遗漏了一些东西,但似乎这个话题也给其他人带来了困惑。尽管如此,我还是没有找到解决这个问题的合适方法。我在 class 定义中直接尝试了配置、factoryConfig 和变量的各种组合,但似乎没有任何效果。
因此,我将非常感谢一个解决方案,或者至少是一个有价值的 link 博客 post 或文档。非常感谢您。
如果相关,我正在使用 ExtJS 6 classic。
原因是您的 tpl
在 prototype and is therefore shared between instances 上。这是我对 Ext 在原型上设置对象而不理解其真正含义的方式的最大不满。这也意味着如果需要,您无权访问 this
,正如您将在我的示例中看到的那样,因为您需要将配置 "pass down" 添加到模板中。
你的好问题实际上是给了我一个很好的简化示例,证明了我一直试图向我的团队提出的观点(自从它是 yui-ext 以来就一直在开发 Ext-JS);
您的 tpl
对象正在 Aft.view.comments.CommentsList.prototype
上设置,因此正在共享。
正确的解决方案是从构造函数(或initComponent
)初始化tpl
,以便为每个实例创建一个新模板。参见 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
在原型上设置某些内容时,这意味着调用者在传入配置对象时仍然可以覆盖它。例如,在上面的 class 中,我可以在实例化时覆盖 tpl
(并破坏 class 的功能)。
// 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)。
我定义了以下 class 扩展 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
}
]
而且不管我输入什么作为参数,我在配置中输入的所有内容似乎都在我的自定义 class 的其他实例之间共享。因此,要么每个 CommentsList 都将参数设置为 true,要么每个都将其设置为 false。我显然遗漏了一些东西,但似乎这个话题也给其他人带来了困惑。尽管如此,我还是没有找到解决这个问题的合适方法。我在 class 定义中直接尝试了配置、factoryConfig 和变量的各种组合,但似乎没有任何效果。
因此,我将非常感谢一个解决方案,或者至少是一个有价值的 link 博客 post 或文档。非常感谢您。
如果相关,我正在使用 ExtJS 6 classic。
原因是您的 tpl
在 prototype and is therefore shared between instances 上。这是我对 Ext 在原型上设置对象而不理解其真正含义的方式的最大不满。这也意味着如果需要,您无权访问 this
,正如您将在我的示例中看到的那样,因为您需要将配置 "pass down" 添加到模板中。
你的好问题实际上是给了我一个很好的简化示例,证明了我一直试图向我的团队提出的观点(自从它是 yui-ext 以来就一直在开发 Ext-JS);
您的 tpl
对象正在 Aft.view.comments.CommentsList.prototype
上设置,因此正在共享。
正确的解决方案是从构造函数(或initComponent
)初始化tpl
,以便为每个实例创建一个新模板。参见 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
在原型上设置某些内容时,这意味着调用者在传入配置对象时仍然可以覆盖它。例如,在上面的 class 中,我可以在实例化时覆盖 tpl
(并破坏 class 的功能)。
// 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)。