我有一个Ext.form.field.Text
,想要覆盖setValue
函数。
在ExtJS中,推荐的方式是什么来覆盖这个类的功能?Ext.override吗?
我有一个Ext.form.field.Text
,想要覆盖setValue
函数。
在ExtJS中,推荐的方式是什么来覆盖这个类的功能?Ext.override吗?
为了澄清:我所谓的真实的类修改是指有意图的对一个类进行永久性修改/扩展,这应该总是通过扩展一个类来完成。但它不是针对特定问题(修复漏洞等)的临时解决方案。
您至少有四种覆盖(Ext)Classes成员的选项
原型 我想是众所周知的,它允许您为类的所有实例覆盖成员。您可以像这样使用它
Ext.view.View.prototype.emptyText = "";
虽然你不能像这样使用它
// callParent is NOT allowed for prototype
Ext.form.field.Text.prototype.setValue = function(val) {
var me = this,
inputEl = me.inputEl;
if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
inputEl.removeCls(me.emptyCls);
me.valueContainsPlaceholder = false;
}
me.callParent(arguments);
me.applyEmptyText();
return me;
};
这里有一个JSFiddle
这种方式不应该用于真正的类修改。
Ext.override 几乎与原型链的作用相同,但它完全适用于 ExtJS 类系统,使您可以使用 callParent()
。
您可以像这样使用它
// callParent is allowed for override
Ext.override('Ext.form.field.Text', {
setValue: function(val) {
this.callParent(['In override']);
return this;
}
});
这里有一个JSFiddle(修复了c-p错误!感谢@nogridbag)
使用场景:我遇到了一个(我认为仍存在的)radiogroup的不良行为,其中ExtJS期望一个对象(键值对)以正确设置值。但我的后端只返回一个整数。我首先使用Ext.override为
setValue()
方法应用了一个修复程序,然后从radiogroup中扩展。在那里,我只是从给定的值创建一个键值对,并使用它调用父方法。
如@rixo所提到的,这可以用于覆盖实例成员。因此,即使是mixins(我自己从未测试过),也可能有资格进行覆盖。
var panel = new Ext.Panel({ ... });
Ext.override(panel, {
initComponent: function () {
// extra processing...
this.callParent();
}
});
这种变体不应该用于真正的类修改。
继承一个现有的类以应用额外的行为和渲染。使用此变体创建一个子类型,使其具有不同的行为,同时又不失原始类型。
在以下示例中,我们通过添加一个名为setColored
的方法来扩展文本字段,并覆盖setValue
方法来处理直接调用setValue
时移除标签颜色的情况。
Ext.define('Ext.ux.field.Text',{
extend: 'Ext.form.field.Text',
widget: 'uxtextfield',
setColored: function(val,color) {
var me = this;
if (me.settedCls) {
me.removeCls(me.settedCls);
}
me.addCls(color);
me.settedCls = color;
me.setValue(val,true);
},
setValue: function(val,take) {
var me = this;
if (!take && me.settedCls) {
me.removeCls(me.settedCls);
}
me.callParent(arguments);
return me;
}
});
这是一个JSFiddle
只覆盖实例在极少数情况下会发生,并且可能不适用于所有属性。在这种情况下(我手头没有示例),您只需对不同行为进行单个操作,就可以考虑仅针对实例覆盖设置。基本上,当您在类创建时应用配置时,您总是这样做,但大多数时间您只覆盖配置属性的默认值,但您也可以覆盖引用函数的属性。这将完全覆盖实现,您可能无法访问基础类型(如果存在),这意味着您无法使用callParent
。您可以尝试使用setValue
来查看它是否不能应用于现有链。但是,再次强调,您可能遇到一些罕见的情况,在开发时即使仅重新实现也很有用。对于这种情况,您应该在创建特定对象后使用Ext.override进行覆盖。
重要提示:如果您不使用Ext.override,则无法通过调用
this
访问类实例!
如果我遗漏了什么或某些内容不准确,请评论或随意编辑。
正如@Eric评论的那样:
这些方法都不允许您覆盖混入项(如Ext.form.field.Field)。由于混合函数在定义类时复制到类中,因此必须直接将覆盖应用于目标类。
Ext.form.field.Field
)。因为混入函数在定义类时被复制到类中,所以你必须直接将覆盖应用于目标类。 - Ericoverride
这样的关键字,否则会出现错误。ExtJS 不支持这个功能。但是你可以添加一个自定义的 Ext.override
来实现,只有在方法不存在时才适用。我只是不会把它命名为 override ;) 另一种方法是在 initComponent
中的 callParent
调用后进行检查,如果方法不存在,则应用它。你可以使用 Ext.applyIf
来实现。但你永远不会知道同名函数是否真的做了相同的事情! - sramethod_exists
函数。当然你永远不会知道这个函数是否完全相同,但在我的情况下(我想要重写 Ext.data.TreeStore
并添加一个名为 commitChanges
的方法,在 4.1.3 版本中似乎没有这个方法),我非常确定如果将来实现了它,它将完全满足我的需求 :) - AsGoodAsItGetsExt.override
,而不仅仅是类,并且在覆盖的方法中使用callParent
(如函数文档中的示例所示)。 - rixo@sra提供的答案很好,对我深入了解Ext中可用的重写功能非常有帮助,但它并未包括我最常用的实现重写的方式,大致如下:
Ext.define('my.application.form.field.Text' {
override: 'Ext.form.field.Text'
getValue: function () {
// your custom functionality here
arguments[1] = false;
// callParent can be used if desired, or the method can be
// re-written without reference to the original
this.callParent(arguments)
}
});
我仍在使用Ext 5,因此我将在Application.js
文件中加载此文件,并在其中添加到requires数组中,这将全局应用override。 我认为Ext 6项目包括一个override文件夹,只需将此文件添加到该文件夹即可确保应用override。
这是我在ExtJS 7中使用的唯一有效方法。
示例:
app/desktop/overrides/Toast.js
Ext.define(null, {
override: 'Ext.window.Toast',
show : function () {
this.callParent();
// Your custom code here...
}
});