2012-05-01 16 views
17

Busco algunos ejemplos para crear un constructor personalizado en mis modelos. Quiero que la estructura sea el modelo/datos diferente luego simplemente establecerlo como atributos.Backbone.js constructor de encargo?

alguien puede mostrar algún ejemplo básico de cómo hacer esto?

Gracias!

+1

Puede transformar el JSON del servidor según sea necesario usando 'parse' (http://documentcloud.github.com/backbone/#Model-parse). Quizás debas aclarar lo que tratas de hacer, un ejemplo podría ser útil. –

Respuesta

39

Si realmente desea anular el constructor, pase una propiedad constructor a Backbone.Model.extend(), por ejemplo:

var Klass = Backbone.Model.extend({ 

    constructor : function (attributes, options) { 

    // ... 

    } 

}); 

Si desea llamar al constructor incorporada desde su constructor personalizado, puede hacer algo como:

var Klass = Backbone.Model.extend({ 

    constructor : function (attributes, options) { 

    Backbone.Model.apply(this, arguments); 

    } 

}); 

O si no desea tener que repetir el nombre del va riable que contiene la clase padre todo el subclase, o que no quieren preocuparse por el valor de esa variable cambiante, que puede hacer algo como lo siguiente:

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 si lo prefiere la forma @Claude suggests, pero repitiendo el nombre de la variable sub clase dentro de la subclase en lugar del nombre de la clase padre var:

var Klass = Backbone.Model.extend(

    { 

    constructor : function (attributes, options) { 

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

    } 

    }, 

    { 

    parent_klass : Backbone.Model.prototype 

    } 

); 

Si quieres más consejos que eso, tendrá que ser más específico acerca de lo que quiere lograr.

Cualquier cosa que lo que desea hacer después de la funcionalidad del constructor incorporada, probablemente debería hacer en initialize().

+1

Tenga cuidado al usar __super__ en combinación con 'this'. 'this' siempre apuntará al objeto que se está creando, lo que lleva a un ciclo infinito. Ver mi respuesta para más información. – Claude

+0

@ Claude Sí, gracias por mencionar eso. He querido actualizar la respuesta re: eso. Deje de usar '__super__' desde que publiqué esta respuesta. – JMM

+0

¿Qué le parece hacer un constructor para cada instancia de un modelo que usa un prototipo? He intentado modificar el método constructor cuando se crea una instancia de Backbone.Model. Deseo realizar un trabajo de autoencuadernación con el framework socket.io del nodo. No, no quiero tener que adjuntar un método de constructor a cada modelo que creo. Agregar un prototipo de trabajos de inicialización; el único problema es que si se pasa uno con el modelo, se anula mediante el método de extensión de subrayado. – kr1zmo

0

Parece que usted está buscando el método initialize. Se llama cuando se crea un nuevo modelo, y se puede utilizar si para lo que se necesita para:

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

new myModel(); 

Si usted está mirando para hacer algo más complicado, es posible reemplazar el método constructor en el núcleo de la espina dorsal. Sin embargo, ese es un negocio mucho más complicado. Mucho mejor para trabajar con métodos expuestos si puedes!

+1

Estoy buscando un constructor personalizado. No quiero que los atributos enviados simplemente se configuren en el modelo. Estoy buscando anular el constructor. – fancy

+1

Por supuesto, puede pasar un hash de opción para 'inicializar', manipularlo dentro de la función y establecer los atributos que necesite desde allí. – rjz

+0

'constructor' está" expuesto ", y los documentos explican cómo puede anularlo. 'initialize' tiene un propósito diferente. – Madbreaks

2

Si desea escribir su modelo por sí mismo, de esta manera:

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

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

Tenga cuidado, creo que es necesario consultar Backbone.Model constructor source code. Pero creo que esta no es una buena idea. Anular initialize método es la manera correcta:

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

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

El método de inicialización 'Backbone.Model' está vacío, no estoy seguro de si tiene sentido llamarlo. – raine

+0

@rane ¿está seguro de que así será en futuras versiones? Definitivamente sabio llamar al súper método. – Madbreaks

6

Así es como reemplazar el valor predeterminado Backbone.Model constructor:

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

Después de que usted tiene que asegurarse de que el prototipo Backbone.Collection utiliza el constructor Backbone.Model actualización:

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

la 'ventaja' de este enfoque en mi opinión es que se puede seguir usando Backbone.Model como su constructor de modelo, lo que hace que el cambio sea más transparente.

+1

+1 por no hacer que mis modelos amplíen algo más – blockhead

7

Como menciono en el comentario, tener cuidado al utilizar this.constructor.__super__ (o this.__super__), no sea que termine en un bucle sin fin (Maximum call stack size exceeded en Chrome).

intente lo siguiente en la consola (por cuenta y riesgo, que dará lugar a bucle sin fin ya mencionado)

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 

La razón es que al crear B, this en el constructor de A puntos a una instancia de B , por lo que this.constructor.__super__.constructor sigue apuntando hacia el constructor de A, que se está llamando una y otra vez.

Si desea "comportamiento previsto", utilice una de las siguientes sintaxis:

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 directamente sin __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

Algo a tener en cuenta al anular el constructor Backbone.Model - si no llama al Backbone.Model.apply, entonces Model.cid puede no estar configurado.

Eso es malo: si cid no está configurado en varios modelos, la colección puede considerarlo como un duplicado del primer modelo de su colección, y no permitirá que se agregue.