2012-05-01 106 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,集合可能会认为它是集合中第一个模型的副本 - 并且不允许添加它。