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

时间:2013-01-10 09:15:49

标签: extjs extjs4 override extjs4.1

我有一个Ext.form.field.Text,我想覆盖setValue函数。

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

3 个答案:

答案 0 :(得分:74)

  

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

至少有四个选项可以覆盖(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 与原型几乎完全相同,但它完全适用于允许您使用callParent()

    的ExtJS类系统

    您可以像

    一样使用它
    // 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延伸。在那里,我只是做了一个   Key-Value-Pair来自给定值并使用父方法调用   这一点。

    提到@rixo这可以用来覆盖实例成员。因此可能有资格覆盖甚至mixins(我从未自己测试过)

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

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

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

    在下面的示例中,我们使用一种方法扩展textfield,以便在设置名为setColored的新值时更改labelcolor,并覆盖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

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

      

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

如果我遗漏某些内容或某些内容(不再)正确,请发表评论或随时进行修改。

@Eric

评论

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

答案 1 :(得分:1)

@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项目包含一个覆盖文件夹,只需将该文件添加到该文件夹​​即可确保应用覆盖。

答案 2 :(得分:0)

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

示例:

app/desktop/overrides/Toast.js

Ext.define(null, {
    override: 'Ext.window.Toast',
    show : function () {
        this.callParent();
// Your custom code here...
    }
});