32

我有一个Ext.form.field.Text并且我想覆盖该setValue功能。

在 ExtJS 中覆盖此类功能的推荐方法是什么?分机覆盖

4

3 回答 3

78

澄清一下: 通过真正的类修改,我指的是对一个类的预期永久修改/扩展,这应该总是通过扩展一个类来完成。但这并不是针对特定问题(错误修复等)的临时解决方案

您至少有四个选项如何覆盖(Ext)类的成员

  • 我猜原型是众所周知的,它允许您覆盖类的所有实例的成员。你可以像这样使用它

    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(修复了 cp 错误!感谢@nogridbag

    用例:我遇到了一个(我认为仍然存在的)radiogroup 的不良行为,其中 ExtJS 期望一个对象(键值对)来正确设置值。但我的后端只有一个整数。我首先使用Ext.override对该setValue() 方法进行了修复,然后从 radiogroup 扩展。在那里,我只是从给定的值创建一个键值对并用它调用父方法。

    正如@rixo提到的,这可用于覆盖实例成员。因此可能有资格覆盖甚至混合(我自己从未测试过)

    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创建特定之后应用覆盖,如上所述。

    重要提示:this如果您不使用Ext.override ,则无法通过调用访问类实例!

如果我遗漏了某些内容或某些内容(不再)正确,请发表评论或随时编辑。

正如@Eric评论的那样

这些方法都不允许您覆盖 mixins(例如 Ext.form.field.Field)。由于 mixin 函数在您定义类时被复制到类中,因此您必须直接将覆盖应用到目标类

于 2013-01-10T09:33:37.277 回答
3

@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 数组中,该数组将覆盖全局应用于应用程序。我认为 Ext 6 项目包含一个覆盖文件夹,只需将此文件添加到该文件夹​​即可确保应用覆盖。

于 2017-05-05T22:52:46.647 回答
1

这是在 ExtJS 7 中对我有用的唯一方法。

例子:

应用程序/桌面/覆盖/Toast.js

Ext.define(null, {
    override: 'Ext.window.Toast',
    show : function () {
        this.callParent();
// Your custom code here...
    }
});
于 2021-06-19T08:43:44.477 回答