web-dev-qa-db-ja.com

ExtJSでクラス/プロパティをオーバーライドするためのベストプラクティス

を持っています Ext.form.field.TextsetValue関数をオーバーライドしたい。

ExtJSでこのクラス機能をオーバーライドする推奨方法は何ですか? Ext.override

31
A1rPun

明確化のために:実際のクラス変更によってつまり、意図したクラスの永続的な変更/拡張、これは常にクラスを拡張することで実行する必要があります。しかし、それは特定の問題(バグ修正など)の一時的な解決策ではありません。

(Ext)クラスのメンバーをオーバーライドする方法には、少なくとも4つのオプションがあります。

  • 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はプロトタイプとほぼ同じですが、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 のおかげです)

    ユースケース:私は、ExtJSが値を正しく設定するためのオブジェクト(キーと値のペア)を期待するラジオグループの悪い動作に直面しました(まだ存在すると思います)。しかし、バックエンドには整数が1つしかありません。最初にExt.overrideを使用してsetValue()メソッドに修正を適用し、その後radiogroupから拡張しました。そこで、指定された値からKey-Value-Pairを作成し、それを使用して親メソッドを呼び出します。

    As @ rixo のように、これはインスタンスメンバをオーバーライドするために使用できます。したがって、ミックスインをオーバーライドする資格がある場合があります(自分でテストしたことはありません)

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

    このバリアントは、実際のクラスの変更には使用しないでください。

  • Extending追加の動作とレンダリングを適用する既存のクラス。このバリアントを使用して、元のタイプを失うことなく異なる動作をするサブタイプを作成します。

    次の例では、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

  • インスタンスごとのオーバーライドは非常にまれなケースで発生し、すべてのプロパティに適用できるわけではありません。そのような場合(私には手元に例はありません)、異なる動作に対する単一のニーズがあり、インスタンスごとに設定をオーバーライドすることを検討するかもしれません。基本的に、クラス作成時に設定を適用するときは常にこのようなことを行いますが、ほとんどの場合、設定プロパティのデフォルト値をオーバーライドするだけでなく、関数を参照するプロパティをオーバーライドすることもできます。これは実装を完全にオーバーライドし、ベースタイプ(存在する場合)へのアクセスを許可しない場合があります。つまり、callParentは使用できません。 setValueで試してみて、既存のチェーンに適用できないことを確認してください。しかし、開発中の場合でも、これが役立つ稀なケースに直面する可能性があり、生産性のために再実装されます。このような場合は、上記のように Ext.override を使用して特定のものを作成した後、オーバーライドを適用する必要があります。

    重要:Ext.override !を使用しない場合、thisを呼び出してクラスインスタンスにアクセスすることはできません。

何かを見逃したか、何かが(もはや)正しくない場合は、コメントするか、自由に編集してください。

@ Ericのコメント通り

これらのメソッドでは、ミックスイン(Ext.form.field.Fieldなど)をオーバーライドできません。ミックスイン関数は、クラスを定義するときにクラスにコピーされるため、ターゲットクラスに直接オーバーライドを適用する必要があります

75
sra

@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そして、それをグローバルにアプリにオーバーライドを適用する必要な配列に追加します。 Ext 6プロジェクトにはオーバーライドフォルダーが含まれており、このフォルダーにこのファイルを追加するだけでオーバーライドが適用されると思います。

1
Grant Humphries