I've been developing Backbone applications for a little while now, and am just starting to learn to use Backbone with Require.js.
In my backbone app that I am refactoring, I defined a namespace like this: App.model.repo
. This model is used over and over again in different views. I do the same thing with a few collections, for example, App.collection.files
. These models and collections are bootstrapped in with the initial index file request.
I did find this example, which looks like a great way to get that bootstrapped data in. However, I am struggling with the best way to reuse/share these models and collection between views.
I can think of three possible solutions. Which is best and why? Or is there another solution I am missing entirely?
Solution 1
Define these common modules and collections in the index (when they are bootstrapped in), and then pass them along to each Backbone view as an option (of initialize
).
define(['jquery', 'underscore', 'backbone', 'handlebars', 'text!templates/NavBar.html'],
function($, _, Backbone, Handlebars, template){
return Backbone.View.extend({
template: Handlebars.compile(template),
initialize: function(options){
this.repoModel = options.repoModel; // common model passed in
}
});
}
);
These seems clean as far as separation, but could get funky quick, with tons of things being passed all over the place.
Solution 2
Define a globals
module, and add commonly used models and collections to it.
// models/Repo.js
define(['backbone'],
function(Backbone){
return Backbone.Model.extend({
idAttribute: 'repo_id'
});
}
);
// globals.js (within index.php, for bootstrapping data)
define(['underscore', 'models/Repo'],
function(_, RepoModel){
var globals = {};
globals.repoModel = new Repo(<?php echo json_encode($repo); ?>);
return globals
}
);
define(['jquery', 'underscore', 'backbone', 'handlebars', 'text!templates/NavBar.html', 'globals'],
function($, _, Backbone, Handlebars, template, globals){
var repoModel = globals.repoModel; // repoModel from globals
return Backbone.View.extend({
template: Handlebars.compile(template),
initialize: function(options){
}
});
}
);
Does this solution defeat the whole point of AMD?
Solution 3
Make some models and collections return an instance, instead of a constructor (effectively making them Singletons).
// models/repo.js
define(['backbone'],
function(Backbone){
// return instance
return new Backbone.Model.extend({
idAttribute: 'repo_id'
});
}
);
// Included in index.php for bootstrapping data
require(['jquery', 'backbone', 'models/repo', 'routers/Application'],
function($, Backbone, repoModel, ApplicationRouter){
repoModel.set(<?php echo json_encode($repo); ?>);
new ApplicationRouter({el: $('.site-container')});
Backbone.history.start();
}
);
define(['jquery', 'underscore', 'backbone', 'handlebars', 'text!templates/NavBar.html', 'models/repo'],
function($, _, Backbone, Handlebars, template, repoModel){
// repoModel has values set by index.php
return Backbone.View.extend({
template: Handlebars.compile(template),
initialize: function(options){
}
});
}
);
This I worry could get real confusing about what is a constructor and what is an instance.
End
If you read this far, you are awesome! Thanks for taking the time.