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

4

3 回答 3

12

从骨干文档

集合还可以通过使用返回模型的函数覆盖此属性来包含多态模型。

var Library = Backbone.Collection.extend({

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

});
于 2013-04-17T01:03:21.160 回答
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/

于 2014-02-13T18:12:52.630 回答
0

覆盖骨干集合的 _prepareModel。集合 new 在定义时使用子类,否则使用默认模型。

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
于 2013-03-20T15:06:54.720 回答