Backbone.Js Collection with Specific Types

一笑奈何 提交于 2020-01-20 19:42:49

问题


I have a BackboneJS collection called History which can contain one of several Backbone JS models (which extend from HistoryItem which extends from Backbone.Model), I trying to find a way to have this recreated when loading, unfortunately it seems BackboneJS collection can only specify at particular model e.g.

HistoryCollection = Backbone.Model.extend({
  model: app.models.HistoryItem
})

What I really need to do is determine this per type, here is what I'd like to do

 HistoryCollection = Backbone.Model.extend({   
  model: function(item) {
       return app.models[item.type];   } })

Any ideas before I fork Backbone to implement this? (i.e. a collection model attribute being able to take a function)


回答1:


Playing around in firebug.. came up with an approach where you can override the parse method of collection instead of specifying the model. Your parse implementation basically becomes a simple factory for filling the collection with models that you want:

var BaseModel  = Backbone.Model.extend({
    meth: function(){ return 'Base method'; },
});

var SubModel = BaseModel.extend({
    meth: function(){ return 'Sub1 method'; }
});

var SubModel2 = BaseModel.extend({
    meth: function(){ return 'Sub2 method'; }
});

var ModelCollection = Backbone.Collection.extend({
    parse: function(data){
        var self = this;
        data.forEach(function(item){
            switch(item.type){
            case 1:
                self.add(new SubModel(data));
                break;
            case 2:
                self.add(new SubModel2(data));
                break;
            default:
                self.add(new BaseModel(data))
        }
});
    }
});

//Example Use
x = new ModelCollection;
x.parse([{type: 1},{type: 2}, {type: 99}]);
x.map(function(e){ return e.meth();});



回答2:


IMHO, I prefer to play with the model method in the collection:

var MyCollection = Backbone.Collection.extend({
  model : function(attrs, options){
    switch (attrs.type) {
            case 1 :
                model = new ModelType1(attrs, options);
                break;

            case 2 :
                model = new ModelType2(attrs, options);
                break;

            default :
                model = new BaseModel(attrs, options);
                break;
    }
  }
});

or using a proxy model:

ProxyModel = Backbone.Model.extend({
 initialize: function() {
   switch (this.get('type')) {
     case 1 :
       model = new ModelType1(attrs, options);
       break;

     case 2 :
       model = new ModelType2(attrs, options);
       break;

     default :
       model = new BaseModel(attrs, options);
       break;
   }
   return new model;
 }
})


var MyCollection = Backbone.Collection.extend({
  model : ProxyModel,
});



回答3:


I've just implemented this feature and started off with Jake Dempsey's advice, however you actually need to override a different method in the collection. This is the code I used:

var MyCollection = Backbone.Collection.extend({

    _prepareModel: function(model, options) {
        if (!(model instanceof Backbone.Model)) {
            var attrs = model;

            switch (attrs.type) {
                case 1 :
                    model = new ModelType1(attrs, { collection: this });
                    break;

                case 2 :
                    model = new ModelType2(attrs, { collection: this });
                    break;

                default :
                    model = new BaseModel(attrs, { collection: this });
                    break;
            }

            if (model.validate && !model._performValidation(attrs, options)) model = false;
        } else if (!model.collection) {
            model.collection = this;
        }

        return model;
    }

});

Note that it is a private(ish) method so something to keep in mind when upgrading Backbone.



来源:https://stackoverflow.com/questions/6061445/backbone-js-collection-with-specific-types

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