2012-05-01 21 views
17

Sto cercando alcuni esempi per la creazione di un costruttore personalizzato sui miei modelli. Voglio la struttura del modello/dati in modo diverso quindi semplicemente impostandola come attributi.Costruttore personalizzato Backbone.js?

Qualcuno può mostrarmi qualche esempio di base su come farlo?

Grazie!

+1

È possibile trasformare il JSON del server secondo necessità utilizzando 'parse' (http://documentcloud.github.com/backbone/#Model-parse). Forse dovresti chiarire cosa stai cercando di fare, un esempio potrebbe aiutarti. –

risposta

39

Se davvero si vuole ignorare il costruttore, passare una proprietà constructor-Backbone.Model.extend(), ad esempio:

var Klass = Backbone.Model.extend({ 

    constructor : function (attributes, options) { 

    // ... 

    } 

}); 

Se si desidera chiamare il costruttore built-in dal tuo costruttore personalizzato, puoi fare qualcosa del tipo:

var Klass = Backbone.Model.extend({ 

    constructor : function (attributes, options) { 

    Backbone.Model.apply(this, arguments); 

    } 

}); 

Oppure se non si desidera ripetere il nome del va riable contenente la classe padre tutta la classe secondaria, o non si vuole preoccupare del valore di quella variabile che cambia, si può fare qualcosa di simile al seguente:

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

O se si preferisce la strada @Claude suggests, ma ripetendo il nome della variabile secondaria di classe all'interno della classe sub al posto del nome della classe genitore var:

var Klass = Backbone.Model.extend(

    { 

    constructor : function (attributes, options) { 

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

    } 

    }, 

    { 

    parent_klass : Backbone.Model.prototype 

    } 

); 

Se volete ulteriori consigli di questo, dovrete essere più specifico su ciò che si vuole realizzare.

Tutto ciò che si desidera eseguire dopo la funzionalità del costruttore incorporato, è consigliabile farlo in initialize().

+1

Fai attenzione nell'uso di __super__ in combinazione con 'this'. 'Questo 'punterà sempre all'oggetto che si sta creando, portando ad un loop infinito. Vedi la mia risposta per maggiori informazioni. – Claude

+0

@Laude sì, grazie per averlo menzionato. Ho intenzione di aggiornare la risposta: questo. Ho smesso di usare '__super__' da quando ho postato questa risposta. – JMM

+0

Che ne dici di creare un costruttore per ogni istanza di un modello usando il prototipo? Ho cercato di modificare il metodo del costruttore quando viene creata un'istanza di Backbone.Model. Voglio eseguire alcuni lavori di rilegatura automatica con il framework socket.io del nodo. BuT Non voglio dover collegare un metodo di costruzione a ciascun modello che creo. Aggiunta di un prototipo di opere di inizializzazione; l'unico problema è che se uno viene passato con il modello, lo sovrascrive tramite il metodo di estensione underscore. – kr1zmo

0

Sembra che stiate cercando il metodo initialize. Si chiama quando si crea un nuovo modello, ed è possibile utilizzare se per tutto ciò che serve per:

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

new myModel(); 

Se stai cercando di fare qualcosa di più coinvolti, è possibile sovrascrivere il metodo constructor nel nucleo Backbone. È un affare molto più complicato, però. Molto meglio lavorare con metodi esposti se puoi!

+1

Sto cercando un costruttore personalizzato. Non voglio che gli attributi inviati vengano semplicemente impostati sul modello. Sto cercando di scavalcare il costruttore. – fancy

+1

Ovviamente è possibile passare un hash di opzioni a "initialize", manipolarlo all'interno della funzione e impostare qualsiasi attributo necessario da lì. – rjz

+0

'costruttore 'è" esposto "e i documenti spiegano come è possibile sovrascriverlo. 'initialize' serve a uno scopo diverso. – Madbreaks

2

Se si vuole scrivere il vostro modello da soli, in questo modo:

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

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

Attenzione, penso che è necessario consultare Backbone.Model costruttore source code. Ma penso che non sia una buona idea. Override initialize metodo è la strada giusta:

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

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

Il metodo di inizializzazione 'Backbone.Model' è vuoto, non è sicuro che ci sia un punto nel chiamarlo. – raine

+0

@rane sei sicuro che sarà il caso nelle versioni future? Sicuramente consigliabile chiamare il metodo super. – Madbreaks

6

Questo è come mi ignorare il Backbone.Model costruttore di default:

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

Dopo di che è necessario assicurarsi che il prototipo Backbone.Collection utilizza il Backbone.Model costruttore di aggiornamento:

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

Il "vantaggio" di questo approccio secondo me è che puoi continuare a utilizzare Backbone.Model come costruttore del tuo modello, il che rende la modifica più trasparente.

+1

+1 per non far estendere qualcos'altro ai miei modelli – blockhead

7

Come menzionato nel commento, fare attenzione quando si utilizza this.constructor.__super__ (o this.__super__), per non finire in un ciclo infinito (Maximum call stack size exceeded in Chrome).

Prova il seguente nella console (a rischio, porterà ad anello chiuso sopra menzionato)

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 

motivo è che durante la creazione B, this nel costruttore per A punti a un'istanza di B , quindi this.constructor.__super__.constructor continua a puntare verso il costruttore di A, che viene chiamato di volta in volta.

Se si vuole "comportamento previsto", utilizzare uno dei seguenti sintassi:

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 

o direttamente senza __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

Qualcosa di essere a conoscenza di quando si esegue l'override del costruttore Backbone.Model - se non chiami Backbone.Model.apply allora Model.cid potrebbe non essere impostato.

Che male - Se cid non è impostato su più modelli, la raccolta potrebbe considerarlo un duplicato del primo modello della raccolta e non consentirà l'aggiunta.