我有动物的集合。
App.Collections.Animals extends Backbone.Collection
model: App.Animal
url: '/animals/' #returns json
而这些动物类:
App.Models.Animal extends Backbone.Model
App.Models.Monkey extends App.Models.Animal
defaults:{type:'Monkey'}
App.Models.Cat extends App.Models.Animal
defaults:{type:'Cat'}
App.Models.Dog extends App.Models.Animal
defaults:{type:'Dog'}
当收集充满了JSON(记录包含type属性),我想模型实例化为子类模型(猴,猫,狗),而不是动物。 你怎么能做到这一点?
从骨干文档 :
集合也可以通过重写该属性与返回模型的功能包含多态模型。
var Library = Backbone.Collection.extend({
model: function(attrs, options) {
if (condition) {
return new PublicDocument(attrs, options);
} else {
return new PrivateDocument(attrs, options);
}
}
});
该解决方案是简单(原谅JS,我不知道CoffeeScript的):
var SmartZoo = Backbone.Collection.extend({
model: function (attrs, options) {
// This code assumes that the object looks something like '{ type: "Cat", ... }'.
switch (attrs.type) {
case 'Cat':
return new Cat(attrs, options);
case 'Dog':
return new Dog(attrs, options);
default: // Unknown subclass
return new Animal(attrs, options);
}
}
});
你必须:
- 包括在模型中的一个属性,从中可以推断出骨干模型的类型来创建。 在这个例子中,我的对象包含名为“类型”的值是表示它的骨干型的全名的属性。 请务必将其设置在默认或模型的初始化,这样你还可以添加真实模型实例集合。
- 定义你的集合的模型属性作为函数。 这个函数的第一个参数将是原始JS对象(如果这就是你传递),或骨干模型的属性对象。 无论哪种方式,你可以访问你的类型字段作为该对象的属性。
- 执行你的逻辑来推断从类型字段的正确模式。
- 返回从模型功能正确模型的实例。
下面是显示了这个行动多态性收集的jsfiddle: http://jsfiddle.net/FiddlerOnTheTarmac/uR2Sa/
覆盖骨干集合的_prepareModel。 定义以外的情况下使用默认的模型收集新用途的子类。
class App.Collections.Animals extends Backbone.Collection
model: App.Models.Animal
_prepareModel: (attrs, options) ->
if attrs instanceof Backbone.Model
attrs.collection = @
return attrs
options || (options = {})
options.collection = @
model_class = APP.Models[attrs.ntype] or this.model
model = new model_class(attrs, options)
if (!model._validate(attrs, options))
false
else
model