2012-10-01 43 views
2

我見過骨幹就繼承了這個問題: Backbone.js view inheritance。有用但不回答我的問題。骨幹傳承 - 深度複製

我遇到的問題是這樣的:

說我有一個類Panel(在這個例子中模式);

var Panel = Backbone.Model.extend({ 
    defaults : { 
     name : 'my-panel' 
    } 
}); 

然後是AdvancedPanel;

var AdvancedPanel = Panel.extend({ 
    defaults : { 
     label : 'Click to edit' 
    } 
}); 

下不起作用:

var advancedPanel = new AdvancedPanel(); 
alert(advancedPanel.get('name')); // Undefined :(

的jsfiddle這裏:http://jsfiddle.net/hWmnb/

我想我可以看到,我可以通過一些定製實現這個自己延長功能,創建一個原型的深層副本,但這似乎是人們可能想從Backbone繼承中獲得的常見事物,是否有一種標準的方法來實現它?

+2

我試了一下,這裏建議:http://stackoverflow.com/questions/6549149/在這個小提琴中擴展了默認的模型 - 超類骨幹-js:http://jsfiddle.net/vesteraas/EXbnb/ –

+0

啊謝謝,我沒有看到這個答案/ queston,但現在我看到它是一個鏈接的。雖然仍然不那麼幹淨,但這很有用......我認爲'默認'是標準Backbone模型屬性,所以應該通過擴展來處理。我猜不是這種情況。還有其他建議嗎? –

回答

2

採摘這件事,我有寫了一個簡單的advancedExtend方法來取代該行(來自this inheritance construct):

Panel.extend = Backbone.Model.extend; 

有:

Panel.extend = advancedExtend; 

advancedExtend方法是這樣的:

function advancedExtend(protoProps, classProps) { 

    var delegate = this.render ? 
         Backbone.View : (this.save ? 
          Backbone.Model : (this.navigate ? 
           Backbone.Router : Backbone.Collection)); 

    var child = delegate.extend.apply(this, [ protoProps, classProps ]); 

    _.defaults(child.prototype.defaults, this.prototype.defaults); 
    _.defaults(child.prototype.events, this.prototype.events); 
    _.defaults(child.prototype.attributes, this.prototype.attributes); 

    return child; 
}; 

注:我意識到delegate的定義是毫無意義的,因爲所有的骨幹原型extend方法都是相同的,但是認爲這對於未來版本可能更強大。

查看JSFiddle here

我很想聽聽老兵骨幹想到這個辦法,因爲它是非標準......

1

的問題是使用JavaScript你沒有經典的繼承,所以你需要做一些特別的東西。

當您使用_.extend時,列表中距離要擴展的對象最右側的對象將在任何名稱衝突中「獲勝」。

你需要做的是要麼覆蓋延伸到處理這些案件的定義,或命名defaults哈希像local_defaults和合並他們在你initialization方法

initialize: function(options){ 
     var attrs = _.extend({}, this.defaults, this.local_defaults); 
     this.set(attrs, {silent: true}); 
    }, 

類似的東西是什麼。您必須將屬性散列設置爲默認值集;通常這發生在模型的構造函數中,但模型只知道該點的默認值。

,如果你重新定義你的local_defaults默認當然,你仍然覆蓋,這樣的話你會尋找到覆蓋延伸。 (我們已經爲在這裏工作了幾個特定的​​情況下完成的,所以樂意幫助,如果你需要這一點。)

+0

這真的有用嗎?當'initialize'函數被調用時,我認爲屬性(和用於髒跟蹤的'previousAttributes')已經從默認設置和實際數據一起設置,在上面的代碼中每個實例都會覆蓋這些數據。 – Greg

+0

@Greg Argh,對不起,打字速度很快。已更新爲我們在生產代碼中使用的內容。類似,但有點不同。使用'set'而不是直接修改'this.attributes'。但是,是的,我們現在在生產中使用它,所以它肯定會工作:) – tkone

+0

不要在這裏挑剔,但是在初始化被調用時,傳遞給構造函數的任何數據屬性都已經設置在模型上。在那個時候設置默認值,是否不會覆蓋這些屬性? '新的AdvancedPanel({名稱:「A」,標籤:「B」})'會一直覆蓋默認值? – Greg

1

有大約走這幾種方法,但在我的應用程序的首選方法是定義「在模型作爲功能默認,所以你可以做一些沿着這些路線:

var Panel = Backbone.Model.extend({ 
    defaults : { 
     name : 'my-panel' 
    } 
}); 

剛剛定義的擴展模型,例如:

var AdvancedPanel = Panel.extend({ 
    defaults: function() { 
     var d = _.result(Panel.prototype, 'defaults'); // doing this as top level might be a function as well 
     return _.extend({}, d, { 
      label : 'Click to edit' 
     }); 
    } 
}); 

,然後在控制檯,你應該得到正確的對於名稱值

var advancedPanel = new AdvancedPanelModel(); 
console.log('advancedPanel', advancedPanel.get('name')); 

而且應該做的伎倆

+1

謝謝,我想這是我應該做的。雖然我仍然有一些問題,也許我對Backbone太期待了......在我看來,如果Backbone在模型(及其他)上提供了「擴展」功能,那麼標準模型屬性應該在繼承中也要考慮。 –

+0

如果你不想在每個模型實例上調用默認函數,你也可以使用'AdvancedPanel.prototype.defaults = _.extend(Panel.prototype.defaults,{** advanced這裏默認是**});'AdvancedPanel'的定義之後。如果你想擴展'events'散列,你也會這樣。 – Greg

3

的骨幹extend功能,設置了原型鏈, 除其他事項外,是通用的,用於視圖,路由器,型號, 和集合。因此,它不知道像defaultsevents細節,不能確定是否延長類型要覆蓋合併父值。前

一種方法是做到這一點明確外的實際定義的:

AdvancedPanel.prototype.defaults = _.extend({}, Panel.prototype.defaults, { 
    label: 'Click me' 
}); 

你想對同與觀點:

​​

實際上,你可以已經在他們的apropriate列出的缺省值如果你喜歡,還可以放置 。你剛纔做的構造函數定義的合併之外:

var Base = Backbone.Model.extend({ 
    defaults: { 
    base: 123 
    } 
}); 

var Extended = Base.extend({ 
    defaults: { 
    extended: 456 
    } 
}); 

Extended.prototype.defaults = _.extend({}, Base.prototype.defaults, Extended.prototype.defaults); 

這將有Extended.defaults包括base,無論屬性傳遞給實例extended和 :

console.log(JSON.stringify(new Extended({ test: 'Hey' }).toJSON())); 
>> {"base":123,"extended":456,"test":"Hey"}