Browser + Backbone.js "ApplicationState" common module
I don't understand how to split some kind of "single" application state object model, between different views using the browser. Books and tutorials often use the global namespace, for example:
var app = app || {};
I have a simple example application consisting 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();
}
});
It seems to work 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 only created once (caching)? Or is there a risk of re-creating / resetting the module?
What's the best practice for my use case? Thank you very much.
source to share
Yes, the example you gave will only have one ApplicationState. Browserify does everything that follows module.exports =
as soon as the js file starts up, and then everything that requires that file is passed a link to the result.
However, it is generally best to avoid sharing this technique between views and instead use a parent view that delegates to subviews. There are several ways to set this up. For guidance on best practices for organizing a basic application, check out this conversation: https://www.youtube.com/watch?v=Lm05e5sJaE8
In this example, I would most likely consider using the Backbone Router . In your example, you have a navigator that changes the "main" view. Backbone.Router intercepts the navigation and checks it against your specified routes by calling your view method. For example:
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 simply transactions
, if you use History of the bbb>) is called to your ContainerView.render('TransactionListView')
. And, as a bonus, if you reload the page, you'll still be looking at TransactionListView
.
Other Notes:
- You want to make sure you discard old views when you replace them (by calling
.remove()
on them) to avoid memory leaks. additional literature - You can add some flexibility to your router and use the controller template to render subviews with this great plugin
source to share