29

私が読んだすべてのExtJSドキュメントと例は、次のようなスーパークラスメソッドを呼び出すことを提案しています。

MyApp.MyPanel = Ext.extend(Ext.Panel, {
  initComponent: function() {
    // do something MyPanel specific here...
    MyApp.MyPanel.superclass.initComponent.call(this);
  }
});

私はかなり長い間このパターンを使用してきましたが、主な問題は、クラスの名前を変更するときに、スーパークラスメソッドへのすべての呼び出しも変更する必要があることです。それは非常に不便です、しばしば私は忘れて、それから私は奇妙なエラーを追跡しなければなりません。

Ext.extend()しかし、私が発見したソースを読むと、代わりに、プロトタイプに追加するsuperclass()またはsuper()メソッドを使用できることがわかりました。Ext.extend()

MyApp.MyPanel = Ext.extend(Ext.Panel, {
  initComponent: function() {
    // do something MyPanel specific here...
    this.superclass().initComponent.call(this);
  }
});

このコードでは、MyPanelの名前を別の名前に変更するのは簡単です。1行を変更するだけです。

しかし、私には疑問があります...

  • 私はこれがどこにも文書化されているのを見たことがなく、古い知恵は、文書化されていない行動に頼るべきではないと言っています。

  • ExtJSソースコードでこれらsuperclass()とメソッドの単一の使用法を見つけられませんでした。supr()使用しないのになぜ作成するのですか?

  • たぶん、これらのメソッドはExtJSの古いバージョンで使用されていましたが、現在は非推奨になっていますか?しかし、それはとても便利な機能のようです、なぜあなたはそれを非推奨にするのですか?

それで、私はこれらの方法を使うべきかどうか?

4

6 に答える 6

29

これは、CallParentを使用したExtJS4で解決されると思います。

Ext.define('My.own.A', {
    constructor: function(test) {
        alert(test);
    }
});

Ext.define('My.own.B', {
    extend: 'My.own.A',

    constructor: function(test) {
        alert(test);

        this.callParent([test + 1]);
    }
});
于 2011-05-04T08:22:49.417 に答える
14

はい、確かに、supr()文書化されていません。ExtJS 3.0.0で使用するのを楽しみにしていました(Extスタッフがフォーラムで返信し、そのバージョンで追加しました)が、ひどく壊れているようです。

現在、継承階層をトラバースするのではなく、1レベル上に移動してから、このレベルでスタックし、無限にループしてスタック(IIRC)を爆破します。そのため、2つ以上続けsupr()て使用すると、アプリが機能しなくなります。supr()ドキュメントにもフォーラムにも有用な情報は見つかりませんでした。

サポートライセンスを取得していないため、メンテナンスリリース3.0.xについてはわかりません...

于 2009-11-12T21:05:00.173 に答える
5

これが私が使っているパターンで、しばらくの間それについてブログを書くつもりでした。

Ext.ns('MyApp.MyPanel');

MyApp.MyPanel = (function(){
  var $this = Ext.extend(Ext.Panel, {
    constructor: function() {
        // Using a 'public static' value from $this
        // (a reference to the constructor)
        // and calling a 'private static' method
        this.thing = $this.STATIC_PROP + privateStatic();
        // Call super using $super that is defined after 
        // the call to Ext.extend
        $super.constructor.apply(this, arguments);
    },
    initComponent: function() {
        $super.initComponent.call(this);
        this.addEvents([Events.SOMETHING]); // missing docs here
    }
  });
  var $super = $this.superclass;

  // This method can only be accessed from the class 
  // and has no access to 'this'
  function privateStatic() {
    return "Whatever";
  }


  /** 
    * This is a private non-static member
    * It must be called like getThing.call(this);
    */
  function getThing() {
     return this.thing;
  }

  // You can create public static properties like this
  // refer to Events directly from the inside
  // but from the outside somebody could also use it as
  //  MyApp.MyPanel.Events.SOMETHING
  var Events = $this.Events = {
      SOMETHING: 'something'
  }

  return $this;
})();

MyApp.MyPanel.STATIC_STRING = 10;

//Later somewhere
var panel = new MyApp.Mypanel();
panel.on(MyApp.Mypanel.Events.SOMETHING, callback);

このパターンを使用して取得できる機能はたくさんありますが、すべてを使用する必要はありません。

于 2010-10-28T00:54:54.900 に答える
3

このあまり知られていないJavascript機能(arguments.callee)を使用できます。

MyApp.MyPanel = Ext.extend(Ext.Panel, {
    constructor: function() {
        // Do your thing
        this.thing = 1;

        // Call super
        arguments.callee.superclass.constructor.apply(this, arguments);
    }
});

MDCのドキュメントを参照してください

編集:実際には、これはコンストラクターではないため、initComponentでは機能しません。私は常にコンストラクターを個人的にオーバーライドします(Ext JSの例が示唆していることにもかかわらず)。これについては少し考え続けます。

于 2009-11-12T20:49:50.780 に答える
2

コードを次のように変更するだけです。

var $cls = MyApp.MyPanel = Ext.extend(Ext.Panel, {
  initComponent: function() {
    // do something MyPanel specific here...
    $cls.superclass.initComponent.call(this);
  }
});

そうすれば、クラス名の単一の参照(現在は$ cls)のみを保持できます。クラスメソッド内でのみ$clsを使用すれば、問題ありません。

于 2011-01-10T10:13:41.367 に答える
0

私は数時間前にこの解決策を思いついた。

function extend (parentObj, childObj) {
    parentObj = parentObj || function () {};

    var newObj = function () {
        if (typeof this.initialize == 'function') {
            this.initialize.apply(this, arguments);
        }
    }

    newObj.prototype.__proto__ = parentObj.prototype;

    for (var property in childObj) {
        newObj.prototype[property] = childObj[property];
    }

    newObj.prototype.superclass = function (method) { 
        var callerMethod = arguments.callee.caller,
            currentProto = this.constructor.prototype.__proto__;

        while (callerMethod == currentProto[method]) {
            currentProto = currentProto.__proto__;
        } 

        return currentProto[method]; 
    };

    return newObj;
}

次に、次のことができます。

var A = function () { 
    this.name = "A Function!";
};

A.prototype.initialize = function () {
    alert(this.name);
}

var B = extend(A, {
    initialize: function () {
        this.name = "B Function!";
        this.superclass('initialize').apply(this);
    }
});

var C = extend(B, {
    initialize: function () {
        this.superclass('initialize').apply(this);
    }
});

(Chromium 8.0.552.237(70801)Ubuntu 10.10)および(Firefox 3.6.13)でのみテストされています。

これが誰かの助けになることを願って、私はほとんどGWTに切り替えていました。

于 2011-01-24T00:32:24.417 に答える