underscore666
underscore666

Reputation: 1739

Using global variables in backbone.js .. best practice

Maybe is just a stupid question.
In all examples I have seen the view model and collections are global variables.
Here an exmaple. introduction-to-backbone.
It will be possible to define model view and collection without using global variables or namespace?
And then how can I access them?

Upvotes: 2

Views: 6956

Answers (2)

Ivan Drinchev
Ivan Drinchev

Reputation: 19581

Well @JayC is actually right about the global namespace and that there is some sort of namespacing convention, but I'm actually fond of using separate modules for every Backbone Class and load it later using one ( or none, if you know what you are doing ) namespace. Let me place and example of no global variables application using CommonJS ( actually there is a pretty good resources out there how to make it with RequireJS ).

What you need is additional library that is very simple and looks like this gist. It basically gives you CommonJS specification, which could be used for separate files or for minified one ( e.g. script.js file ).

So imagine you have 4 files, named : model.js, collection.js, view.js, app.js and they look like this :

// model.js
this.require.define({'model.js': function(exports, require, module) {(function() {
    var MyModel = Backbone.Model.extend({
        ...
    });

    module.exports = MyModel;
}).call(this)}});

// collection.js
this.require.define({'collection.js': function(exports, require, module) {(function() {
    var MyCollection = Backbone.Collection.extend({
        model : require('model.js');
    });

    module.exports = MyCollection;
}).call(this)}});

// view.js
this.require.define({'view.js': function(exports, require, module) {(function() {
    var MyView = Backbone.View.extend({
        initialize: function() {
            var Collection = require('collection.js');
            this.collection = new Collection();
        }
    });

    module.exports = MyView;
}).call(this)}});

// app.js
this.require.define({'app.js': function(exports, require, module) {(function() {
    var View = require('view.js');

    $(function() {
        new View();
    });
}).call(this)}});    

Your script tags in the html file should look like this :

<script src='jquery-underscore-backbone.js'></script>
<script src='commonjs.js'></script> <!-- this is the library from the gist -->
<script src='model.js'></script>
<script src='collection.js'></script>
<script src='view.js'></script>
<script src='app.js'></script>

You can minify all files and load only one ( e.g. script.js ) with the minified content of all those files and will also work.

By doing this you will have no global namespace population, no App.Class, no App.Collection ... etc. If you are sure what you are doing, you don't even have to have window.app variable.

I know it looks ugly, because of the wrapper, but there are frameworks that wrap this automagically OR if you use AJAX module loading ( requireJS ) you won't need to use this wrapping function.

Good example ( node.js ) of this is : Stich

Upvotes: 2

JayC
JayC

Reputation: 7141

You can define your Models and Collections (and their respective instances) anywhere you want to. I would recommend some sort of global namespacing convention for the models, etc, just for reuse. A simple way to do this would be:

window.ProjectModels = window.ProjectModels || {};  //use existing namespace  or create a new one.
ProjectModels.SomeModel = Backbone.Model.extend({ ...});
ProjectModels.SomeOtherModel = Backbone.Model.extend({ ...});
ProjectModels.SomeRelatedModel = ProjectModels.SomeModel.extend({ ...});
...
window.ProjectViews = window.ProjectViews || {};  //use existing namespace  or create a new one.
ProjectViews.SomeModelView = Backbone.View.extend({ ...});
ProjectViews.SomeOtherModelView = Backbone.View.extend({ ...});
ProjectViews.SomeRelatedModelView = ProjectViews.SomeModel.extend({ ...});

You may wonder why I haven't put collections in their own namespace. The only reason I haven't put collections in their own namespace is that I can see some cases where I might extend Backbone.Model for some sort of hierarchical collection/thing; also I can tell models apart from collections because I have a convention of naming collections [Something]Collection... In other words, I have no good reason, I just do it to my taste.

Upvotes: 2

Related Questions