2009-11-12 64 views
28

所有ExtJS的文檔和例子我已閱讀建議調用父類的方法是這樣的:更好的方法來調用父類方法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別的東西很簡單 - 我只是必須改變一條線。

但我懷疑...

  • 我還沒有看到這個記錄任何地方和舊的觀念認爲,我不應該依靠無證行爲。

  • 我沒有在ExtJS源代碼中找到這些superclass()supr()方法的單個用法。爲什麼在你不使用它們時創建它們?

  • 也許這些方法在某些舊版本的ExtJS中使用,但現在不推薦使用?但它似乎是一個非常有用的功能,爲什麼你會棄用它?

那麼,我應該使用這些方法嗎?

+0

其實,你可以試試'this.constructor.superclass.initComponent.call(this);'? – neonski 2009-11-12 21:24:04

+0

謝謝,但這與Jabe描述的問題相同 - 它只適用於一個層次的層次結構。 – 2009-11-13 08:44:53

回答

13

是的,supr()沒有記錄。我一直期待在ExtJS 3.0.0中使用它(一個Ext的工作人員在論壇中回覆,他們已經在該版本中添加了它),但它似乎非常糟糕。

它目前沒有遍歷繼承層次結構,而是上升一層,然後卡在這個層面上,無休止地循環並炸燬堆棧(IIRC)。所以,如果你連續有兩個或更多的supr(),你的應用會中斷。我在文檔和論壇上都沒有找到關於supr()的任何有用信息。

我不知道關於維護版本3.0.x的,因爲我沒有得到的支持許可證...

+0

謝謝,它確實不適用於多層次的繼承層次結構。供參考:3.0.3在這方面沒有任何改變。 – 2009-11-13 08:47:42

+1

仍然是Sencha Touch的案例1.1 – Vitaly 2011-05-06 13:48:33

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 documentation

編輯:其實,這是不會有initComponent的工作,因爲它不是」 t構造函數。我總是個人重寫構造函數(儘管Ext JS示例提供了這些內容)。將繼續考慮這一點。

+0

已被棄用。 – Jabe 2009-11-12 20:51:48

+3

JavaScript 1.4:棄用被調用方作爲Function.arguments的一個屬性,將其保留爲函數的本地參數變量的屬性。不一樣的東西! – neonski 2009-11-12 20:56:28

+0

啊,對不起,你是對的。我把它與完全不贊成使用的'調用者'混淆了。去除被調用者將會非常混亂。 – Jabe 2009-11-12 21:12:29

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); 

有很多的功能,你使用這種模式,但你不必使用所有這些

+0

不錯,但是這種方法引入了很多樣板代碼,如果調用大量的父類方法,這可能會很好,但我通常只需要調用initComponent()的父類和沒有別的,在這種情況下額外的代碼是恕我直言,不值得。 – 2010-11-02 13:24:29

+0

是的,這種模式是所有的OO代碼使用繼承,你會調用父母的方法。在Ext中,我經常從父母處調用onRender,afterRender,beforeDestroy,因爲我重寫了它。 – 2010-12-23 18:49:16

+0

這太好了,謝謝!我特別喜歡這個,因爲如果正確完成,它可以通過JSLint/[JSHint](http://jshint.com/)。我有一些問題_linting_ [這是來自舊Sencha教程的格式](http://www.sencha.com/learn/legacy/Tutorial:Extending_Ext_for_Newbies#Extending_Functionality)。 – blong 2012-03-08 22:21:22

2

我會簡單地改變你的代碼:

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

那方式你只保留一個你的類名稱,現在$ cls的引用。只在你的類方法中使用$ cls,你會沒事的。

+1

如果我將每個類包裝在閉包中,此解決方案將工作。目前我沒有,所以這個解決方案不起作用。也許在某一天我會,所以這可以變得可行。 – 2011-01-10 16:28:54

0

我想出了這個解決方案在幾個小時前heheh ...

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); 
    } 
}); 

測試只(鉻8.0.552.237(70801) Ubuntu 10.10) 和(Firefox 3.6.13)。

希望這有助於某人,我幾乎切換到GWT。

+1

'Function.caller'和'Object .__ proto__'都是非標準的。此外,後者已被棄用。雖然,這個想法看起來很有趣。 – 2011-01-26 22:13:16

29

我認爲這是用callParent在ExtJS 4中解決的。

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]); 
    } 
}); 
+1

+1正是我在找的:) – jrharshath 2011-09-01 07:14:52

+1

這個問題涉及到Ext JS 3.x(對於稍後可能會閱讀的用戶) – blong 2013-01-23 23:03:25