Reputation: 9400
I don't understand how to share some sort of "singleton" application-state holding object model, between different views, using browserify. Books and tutorials often use a global namespace such as:
var app = app || {};
I have a simple example app which consists of:
app.js
var $ = require('jquery');
var Backbone = require('backbone');
Backbone.$ = $;
var MenuView = require('./views/MenuView');
var ContainerView = require('./views/ContainerView');
new MenuView();
new ContainerView();
MenuView.js
var Backbone = require('backbone');
var ApplicationState = require('../models/ApplicationState');
module.exports = Backbone.View.extend({
el: '#menuView',
events: {
'click .menuLink': 'changePage'
},
changePage: function(event) {
event.preventDefault();
var viewName = $(event.target).attr('data-view');
ApplicationState.set('currentView',viewName);
}
});
ContainerView.js
var Backbone = require('backbone');
var ApplicationState = require('../models/ApplicationState');
module.exports = Backbone.View.extend({
el: '#containerView',
initialize: function() {
this.listenTo( ApplicationState, 'change', this.render );
this.render();
},
render: function() {
this.$el.html( ApplicationState.get('currentView') );
},
close: function() {
this.stopListening();
}
});
This seems working using this approach:
ApplicationState.js var Backbone = require('backbone');
var ApplicationState = Backbone.Model.extend({
defaults: {
currentView: 'TransactionListView'
}
});
module.exports = new ApplicationState();
Is the ApplicationState module really created only once (caching) ? Or is there the risk of recreating / resetting the module?
What is the best practice for my use case? Thank you a lot.
Upvotes: 3
Views: 634
Reputation: 197
Yes, there will only be one ApplicationState in the example you gave. Browserify executes anything following module.exports =
as soon as the js file is run and then anything that requires that file is passed a reference to the result.
However it’s generally better practice to avoid sharing state this way between views and instead use a parent view that delegates to subviews. There are a number of ways to set this up. For ideas on best practices for organizing a backbone app, check out this talk: https://www.youtube.com/watch?v=Lm05e5sJaE8
For the example you gave I would highly consider using Backbone's Router. In your example you have a nav that changes the "main" view. Backbone.Router intercepts navigation and checks it against your specified routes calling your view method. For instance:
router.js
module.exports = Backbone.Router.extend({
initialize: function(options){
this.ContainerView = new ContainerView();
},
routes: {
'transactions': 'showTransactionListView',
'transaction/:id': 'showTransactionDetailView'
},
showTransactionListView: function() {
this.ContainerView.render('TransactionListView');
},
showTransactionDetailView: function(id) {
this.ContainerView.render('TransactionDetailView', id);
}
});
Then any link to #transations
(or just transactions
if you're using Backbone History) will call your ContainerView.render('TransactionListView')
. And, as a bonus, if you reload the page you'll still be looking at TransactionListView
.
Other notes:
.remove()
on them) so as to avoid memory leaks. Further ReadingUpvotes: 5