【问题标题】:Best practice for overriding classes / properties in ExtJS?在 ExtJS 中覆盖类/属性的最佳实践?
【发布时间】:2012-12-24 15:04:05
【问题描述】:

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

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

【问题讨论】:

  • 我编辑了这个问题,使其更具建设性。请重新打开这个问题,因为答案对 ExtJs 社区非常有用。

标签: extjs extjs4 overriding extjs4.1


【解决方案1】:

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

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

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

    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

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

    正如@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

评论的那样

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

【讨论】:

  • @A1rPun 我做了一个编辑,我认为它解释得更好,更深入
  • 哇,这超出了我的要求!谢谢!
  • 很好的答案,但我想提一点小警告。这些方法都不允许您覆盖 mixins(例如Ext.form.field.Field)。由于 mixin 函数在您定义类时被复制到类中,因此您必须直接将覆盖应用到目标类。
  • @AsGoodAsItGets 我认为您在谈论类似在其他语言中所做的事情,您需要使用像 override 这样的关键字,否则会出现错误。 ExtJS 不支持这个开箱即用。但是您可以为此添加自定义Ext.override,这仅适用于该方法不存在的情况。我只是不会将其命名为覆盖 ;) 另一种方法是在 callParent 调用之后的 initComponent 内。您现在可以检查方法是否存在,如果不存在则应用它。为此,您将使用Ext.applyIf。但是你永远不会知道同名的函数是否真的做同样的事情!
  • 可能有点令人惊讶,但您可以在实例上使用Ext.override——不仅是类——并让callParent在被覆盖的方法中工作(如函数文档中的示例所示) .
【解决方案2】:

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

【讨论】:

  • 感谢详细解释和示例。
【解决方案3】:

这是在 ExtJS 7 中唯一适合我的方法。

例子:

app/desktop/overrides/Toast.js

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 1970-01-01
  • 1970-01-01
  • 2012-09-11
  • 2010-09-20
  • 2017-08-07
  • 1970-01-01
相关资源
最近更新 更多