覆盖ExtJS中的类/属性的最佳实践?

A1r*_*Pun 31 overriding extjs extjs4 extjs4.1

我有一个Ext.form.field.Text,我想要覆盖该setValue功能.

在ExtJS中覆盖此类功能的推荐方法是什么?Ext.override

sra*_*sra 75

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

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

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

    Ext.view.View.prototype.emptyText = "";
    
    Run Code Online (Sandbox Code Playgroud)

    虽然你不能像它一样使用它

    // 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;
    };
    
    Run Code Online (Sandbox Code Playgroud)

    这是一个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;
        }
    });
    
    Run Code Online (Sandbox Code Playgroud)

    这是一个JSFiddle(修复了cp错误!感谢@nogridbag)

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

    正如@rixo所提到的,这可以用于覆盖实例成员.因此可能有资格覆盖甚至mixins(我从未测试过它)

    var panel = new Ext.Panel({ ... });
    Ext.override(panel, {
        initComponent: function () {
            // extra processing...
    
            this.callParent();
        }
    });
    
    Run Code Online (Sandbox Code Playgroud)

    此变体不应用于实际类修改.

  • 扩展现有类以应用其他行为和呈现.使用此变体可以创建一个行为不同的子类型,而不会丢失原始类型.

    在下面的示例中,我们使用一种方法扩展textfield,以便在设置调用的新值时更改labelcolor,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;
        }
    });
    
    Run Code Online (Sandbox Code Playgroud)

    这是一个JSFiddle

  • 在极少数情况覆盖每个实例,并且可能不适用于所有属性.在这种情况下(我手边没有示例),您只需要一个不同的行为,您可以考虑覆盖每个实例的设置.基本上,当您在类创建上应用配置时,您始终会执行此类操作,但大多数时候您只是覆盖配置属性的默认值,但您也可以覆盖引用函数的属性.这完全覆盖了实现,您可能允许无权访问basetype(如果存在),这意味着您无法使用callParent.您可以尝试使用它setValue以查看它无法应用于现有链.但同样,你可能会面临一些罕见的情况,这种情况很有用,即使它只是在开发过程中并重新实现以提高效率.对于这种情况,您应该在使用Ext.override创建特定内容后应用覆盖,如上所述.

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

如果我遗漏某些东西或某些东西(不再)正确,请评论或随意编辑.

@Eric评论

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

  • 很好的答案,但我想提一个小问题.这些方法都不允许您覆盖mixins(例如`Ext.form.field.Field`).由于在定义类时将mixin函数复制到类中,因此必须直接将覆盖应用于目标类. (5认同)
  • 有点令人惊讶的是,但你可以在实例上使用`Ext.override` - 不仅仅是类 - 并且在重写方法中使用`callParent`(如函数文档中的示例所示). (2认同)