2012-05-01 142 views
17

我找了我的模型創建自定義構造函數的一些例子。我希望結構的模型/數據不同,然後將其設置爲屬性。Backbone.js自定義構造函數?

有人能告訴我如何做到這一點一些基本的例子嗎?

謝謝!

+1

您可以根據需要使用'parse'(http://documentcloud.github.com/backbone/#Model-parse)來轉換服務器的JSON。也許你應該澄清你想要做什麼,一個例子可能會有所幫助。 –

回答

39

如果你真的想重寫構造函數,一個constructor財產傳給Backbone.Model.extend(),如:

var Klass = Backbone.Model.extend({ 

    constructor : function (attributes, options) { 

    // ... 

    } 

}); 

如果你要撥打的內置構造從您的自定義構造函數,你可以這樣做:

var Klass = Backbone.Model.extend({ 

    constructor : function (attributes, options) { 

    Backbone.Model.apply(this, arguments); 

    } 

}); 

或者,如果你不想有重複VA的名字含可變結構父類遍佈子類,或者你不想擔心變量變化的值,你可以這樣做以下:

var Klass; 

var parent_klass = Backbone.Model.prototype; 

(function (parent_klass) { 

    Klass = parent_klass.constructor.extend({ 

    constructor : function (attributes, options) { 

     parent_klass.constructor.apply(this, arguments); 

    } 

    }); 

})(parent_klass); 

或者,如果你喜歡的方式@Claude suggests,但子類而不是父類的變量名稱中重複的子類變量名:

var Klass = Backbone.Model.extend(

    { 

    constructor : function (attributes, options) { 

     Klass.parent_klass.constructor.apply(this, arguments); 

    } 

    }, 

    { 

    parent_klass : Backbone.Model.prototype 

    } 

); 

如果你想比這更多的建議,你就必須要更具體的瞭解你想要完成的任務。

任何東西,你只是想內置構造功能後做,你應該做initialize()

+1

將__super__與'this'結合使用時要小心。 'this'將始終指向正在創建的對象,導致無限循環。查看我的回覆以獲取更多信息。 – Claude

+0

@Claude是的,謝謝你提到這一點。我一直想要更新答案:那。自發布此答案以來,我已停止使用'__super__'。 – JMM

+0

如何使用原型爲模型的每個實例創建構造函數?當創建一個Backbone.Model的實例時,我一直試圖修改構造函數方法。我想用節點的socket.io框架執行一些自動綁定工作。 BuT我不想爲每個創建的模型都附加一個構造函數方法。添加初始化作品的原型;唯一的問題是如果通過模型傳遞它,它會通過下劃線擴展方法覆蓋它。 – kr1zmo

0

這聽起來像你正在尋找的initialize方法。當你創建一個新的模式,它被稱爲,如果任何你需要它,你可以使用:

var myModel = Backbone.Model.extend({ 
    initialize: function() { 
    // do something besides setting attributes or model 
    alert('myModel is ready for action!'); 
    } 
}); 

new myModel(); 

如果你希望做一些更復雜,你可能會覆蓋在骨幹核心constructor方法。不過,這是一件更棘手的事情。如果可以,更好地使用暴露的方法!

+1

我正在尋找一個自定義構造函數。我不希望傳入的屬性只是在模型上設置。我正在尋找重寫構造函數。 – fancy

+1

您當然可以將選項散列傳遞給'initialize',在函數中對其進行處理,並從那裏設置您需要的任何屬性。 – rjz

+0

'構造函數'是「暴露的」,文檔解釋瞭如何覆蓋它。 'initialize'服務於不同的目的。 – Madbreaks

2

如果你想自己來寫你的模型,像這樣:

var YourModel = function() { 
    // your constructor here 
}; 

_.extend(YourModel.prototype, Backbone.Model.prototype, { 
    // your model method here 
}); 

要小心,我認爲你需要諮詢Backbone.Model構造source code。但我認爲這不是一個好主意。覆蓋initialize方法是正確的方式:

var YourModel = Backbone.Model.extend({ 
    initialize: function (attrs, options) { 
     Backbone.Model.prototype.initialize.apply(this, arguments); // call super constructor 

     // your constructor code here 
    } 
}); 
+0

'Backbone.Model'初始化方法是空的,不知道是否有任何意見調用它。 – raine

+0

@你確定將來的版本會出現這種情況嗎?絕對明智地稱呼超級方法。 – Madbreaks

6

這是我如何覆蓋默認的構造函數Backbone.Model:

Backbone.Model = (function(Model) { 
    // Define the new constructor 
    Backbone.Model = function(attributes, options) { 
    // Your constructor logic here 
    // ... 
    // Call the default constructor if you wish 
    Model.apply(this, arguments); 
    // Add some callbacks 
    this.on('event', this.myCallback, this); 
    }; 
    // Clone static properties 
    _.extend(Backbone.Model, Model);  
    // Clone prototype 
    Backbone.Model.prototype = (function(Prototype) { 
    Prototype.prototype = Model.prototype; 
    return new Prototype; 
    })(function() {}); 
    // Update constructor in prototype 
    Backbone.Model.prototype.constructor = Backbone.Model; 
    return Backbone.Model; 
})(Backbone.Model); 

之後,你必須確保Backbone.Collection原型使用更新Backbone.Model構造:

_.extend(Backbone.Collection.prototype, { 
    model: Backbone.Model 
}); 

在我看來,這種方法的「優勢」是,你可以繼續使用Backbone.Model作爲模型的構造,這使得變化更加透明。

+1

+1不讓我的模型擴展別的東西 – blockhead

7

正如我在評論中提到的,在使用this.constructor.__super__(或this.__super__)時要小心,以免最後陷入無限循環(Chrome中的Maximum call stack size exceeded)。

嘗試在控制檯下(在自己的風險,這將導致上述提到的無限循環)

var A = Backbone.Model.extend({constructor: function() { 
    console.log("log: A"); 
    this.constructor.__super__.constructor.apply(this, arguments); 
}}); 

var B = A.extend({constructor: function() { 
    console.log("log: B"); 
    this.constructor.__super__.constructor.apply(this, arguments); 
}}); 

new A(); 
// log: A 
// > Backbone.model.extend.constructor 
new B(); 
// log: B 
// (8192) log: A 
// > RangeError: Maximum call stack size exceeded 

原因是,在構造函數A點創建BthisB實例時,因此this.constructor.__super__.constructor一直指向A的構造函數,這是一次又一次的調用。

如果你想「預期的行爲」,請使用以下語法之一:

var A = Backbone.Model.extend({constructor: function() { 
    console.log("log: A"); 
    A.__super__.constructor.apply(this, arguments); 
}}); 

var B = A.extend({constructor: function() { 
    console.log("log: B"); 
    B.__super__.constructor.apply(this, arguments); 
}}); 

new A(); 
// log: A 
// > Backbone.model.extend.constructor 
new B(); 
// log: B 
// log: A 
// > A.extend.constructor 

,或者直接不__super__

var A = Backbone.Model.extend({constructor: function() { 
    console.log("log: A"); 
    Backbone.Model.apply(this, arguments); 
}}); 

var B = A.extend({constructor: function() { 
    console.log("log: B"); 
    A.apply(this, arguments); 
}}); 

new A(); 
// log: A 
// > Backbone.model.extend.constructor 
new B(); 
// log: B 
// log: A 
// > A.extend.constructor 
-1

一個需要注意重寫Backbone.Model構造函數時的 - 如果您不撥打Backbone.Model.apply,則可能不會設置Model.cid。

這很糟糕 - 如果未在多個模型中設置cid,集合可能會認爲它是集合中第一個模型的副本 - 並且不允許添加它。