Backbone Collection of polymorphic Models

匿名 (未验证) 提交于 2019-12-03 08:41:19

问题:

I have a collection of Animals.

App.Collections.Animals extends Backbone.Collection   model: App.Animal   url: '/animals/' #returns json 

And these animal classes:

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'} 

When collection is filled with JSON (records contain the type attribute) I want models to be instantiated as sub-classed models (Monkey,Cat,Dog) and not as Animal. How can you achieve this?

回答1:

From Backbone documentation:

A collection can also contain polymorphic models by overriding this property with a function that returns a model.

var Library = Backbone.Collection.extend({    model: function(attrs, options) {     if (condition) {       return new PublicDocument(attrs, options);     } else {       return new PrivateDocument(attrs, options);     }   }  }); 


回答2:

The solution is straightforward (pardon the JS, I don't know 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);         }     } }); 

You have to:

  1. Include an attribute in your model from which you can infer the type of Backbone model to create. In this example, my objects contain an attribute called "type" whose value is the full name of the Backbone type that represents it. Be sure to set it in the defaults or initialize of your Model so that you can also add real model instances to the collection.
  2. Define the models property of your collection as a function. The first parameter to this function will be the raw JS object (if that's what you passed in), or the attributes object of a Backbone model. Either way, you can access your type field as a property of this object.
  3. Execute your logic to infer the proper model from your type field.
  4. Return an instance of the correct model from the models function.

Here is a JSFiddle that shows this polymorphic collection in action: http://jsfiddle.net/FiddlerOnTheTarmac/uR2Sa/



回答3:

Override backbone collection's _prepareModel. The collection new uses subclasses when defined otherwise uses the default model.

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 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!