简体   繁体   中英

Backbone.js What is the purpose of specifying a model in collection

Here is what I am trying to understand.

Often times I find myself writing backbone like this:

var CallModel = Backbone.Model.extend({
});

var CallsCollection = Backbone.Collection.extend({
    model: CallModel,
    url: 'url/to/external/json'
});

It is a very basic example but as you can see, there is nothing really in the model all the data is coming into the Collection via an external url call to a json file that is build from a database.

So whats the purpose of the model? I am sure that I am probably not using backbone.js to its fullest extent which is why I am here asking you guys.

You don't need to specify a model. A Backbone collection will default to using Backbone.Model if you don't specify this option. The following would work equally well if you don't need the models of the collection to be of a particular instance.

var CallsCollection = Backbone.Collection.extend({
    url: 'url/to/external/json'
});

Reference

EDIT

In essence, specifying the model option within a collection is just a way to ensure that objects added to this collection will be instances of that particular model class. If the models being added to your collection don't have any custom behaviour outside of what is available to Backbone.Model, you don't need to create and specify a model as Backbone collections will default to using an instance of Backbone.Model as I have already mentioned. If, however, you wanted to ensure that models added to a particular collection were of a particular type and shared customized behaviour (eg validations, defaults, etc.), you would create your own model class by extending Backbone.Model and specifying this in the collection. I hope this clears things up for you.

First of all, " there is nothing really in the model all the data is coming into the Collection via an external url call " - this is not true.

Let's assume you've the following:

//Model
var CallModel = Backbone.Model.extend({
  defaults: {      
    cost:0,
    duration:0
  }
});

( without custom attributes or methods, there is no point in extending the original Backbone.Model )

//Collection
var CallsCollection = Backbone.Collection.extend({
  model: CallModel,
  url: 'url/to/external/json'
});

And the json data returned from service, probably something like:

//Response
{
   callSummary: {
     missed: 2,
     received: 3,
     totalCalls:5
     totalDuration: 20
   }
   calls: [{
         id:001,
         caller:"Mr.A",
         callee:"Mr.B",
         cost:1,
         duration:5
      },{
         id:002,
         caller:"Mr.X",
         callee:"Mrs.Y",
         cost:1,
         duration:7
      },{
         id:003,
         caller:"Mr.A",
         callee:"Mrs.B",
         cost:1,
         duration:8
  }],
  //and more additional information from your db
}

Now you populate your collection with data by calling it's fetch method:

CallsCollection.fetch();

Your collection should look something like:

{
 models: [{
   attributes: {
     callSummary: {},
     calls: [{},{},{}],
     ...
   },
   ...
 }],
 length:1,
 url: "url/to/external/json",
 ...
}

The data will be added to a model 's attribute hash. If you don't specify a particular model, as Bart mentioned in his answer , backbone will populate the collection with a Backbone.Model instance: Which is still not much useful - Wew... A collection with single model having entire response data inside it's attributes as it is...

At this point, you're wondering why did I even bother creating a model, and then a collection ..?

The problem here is Collections are derived from Arrays , while Models are derived from Objects. In this case, our root data structure is an Object (not an Array), so our collection tried to parse the returned data directly into a single model .

What we really want is for our collection to populate its models from the "calls" property of the service response. To address this, we simply add a parse method onto our collection:

var CallsCollection = Backbone.Collection.extend({
  model: CallModel,
  url: 'url/to/external/json',
  parse: function(response){
    /*save the rest of data to corresponding attributes here*/
    return response.calls; // this will be used to populate models array
  }
});

Now your collection will be something like the following:

{
 models: [{
         ...
         attributes: {
           ...
           id:001,
           caller:"Mr.A",
           callee:"Mr.B",
           cost:1,
           duration:5
         }
      },{
         ...
         attributes: {
           ...
           id:002,
           caller:"Mr.X",
           callee:"Mrs.Y",
           cost:1,
           duration:7
         }
      },{
         ...
         attributes: {
           ...
           id:003,
           caller:"Mr.A",
           callee:"Mrs.B",
           cost:1,
           duration:8
       }
   }],
 length:3,
 url: "url/to/external/json",
 ...
}

This - is what we want! : Now it is very easy to handle the data: You can make use of the add, remove, find, reset and handful of other collection methods effectively.

You can pass this models array into your templating library of choice, probably with two way bindings: When the respective view for one of the call model changes, the particular model will be updated, events will propagate from your models to the collection, and the particular model will be passed into the handler functions.

You can now call fetch, save, destroy, clear and a lot of other methods with ease on single unit's of data ( each model ), rather than hurdle with the entire data saved in a single model - which is pretty much useless, you've to iterate through the response data manually and perform CRUD and similar operations by your own, and in most cases: re-render the entire collection view. which is very, very bad and totally unmaintainable.

To conclude : If your data source doesn't return an array of objects, or you don't parse the response and return an array of objects from which n number of models are to be populated - Then defining a collection is pretty much useless.

Hopefully, now you get the idea.

Very helpful source of info:

Sounds Weird but this is the way.

Every collection in backbone, must represent a model, so basically a collections is a list of models.

Even if your model has no data, you need to indicate it when you create a Collection.

This is how backbone works for collections.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM