2013-03-20 71 views
9

我有一个动物的集合。多态模型的主干集合

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(记录包含属性),我想模型实例化为子类模型(猴子,猫,狗)而不是动物。你怎么能做到这一点?

回答

12

从骨干documentation

集合也可以通过重写此 属性与返回模型的功能包含多态模型。

var Library = Backbone.Collection.extend({ 

    model: function(attrs, options) { 
    if (condition) { 
     return new PublicDocument(attrs, options); 
    } else { 
     return new PrivateDocument(attrs, options); 
    } 
    } 

}); 
0

覆盖主干集合的_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 
6

的解决方案是简单(原谅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); 
     } 
    } 
}); 

你必须:

  1. 包括来自你的模型属性您可以推断出要创建的Backbone模型的类型。在这个例子中,我的对象包含一个名为“type”的属性,其值是代表它的Backbone类型的全名。一定要将其设置为默认值或初始化模型,以便您还可以将真实模型实例添加到集合中。
  2. 定义您的集合的模型属性作为一个函数。这个函数的第一个参数是原始JS对象(如果这是你传入的),或Backbone模型的属性对象。无论哪种方式,您都可以访问您的类型字段作为此对象的属性。
  3. 执行你的逻辑来从你的类型字段推断出合适的模型。
  4. 从模型函数中返回正确模型的实例。

这里是一个的jsfiddle显示了动作中多态集合:http://jsfiddle.net/FiddlerOnTheTarmac/uR2Sa/

+0

只要注意的是,如果收集可能有很多的模型'如果();否则如果;其他'是''开关'更高性能 – seebiscuit 2016-01-25 20:05:12