问题
This is a followup question from Backbone boilerplate: "this.model is undefined". I was able to work out some of the structure, but have run into a new problem. I'm using backbone boilerplate, which uses the layoutManager adapter for setting the views. The main view, as well as the subsequent first view, seems to be loading all of the assets correctly, though the subsequent view seems to be firing before the main view gets loaded in. Here is my router file:
define([
// Application.
"app",
//Modules
"modules/homepage"
],
function (app, Homepage) {
"use strict";
// Defining the application router, you can attach sub routers here.
var Router = Backbone.Router.extend({
initialize: function(){
var collections = {
homepage: new Homepage.Collection()
};
_.extend(this, collections);
app.useLayout("main-frame").setViews({
".homepage": new Homepage.Views.Index(collections)
}).render();
},
routes:{
"":"index"
},
index: function () {
this.reset();
},
// Shortcut for building a url.
go: function() {
return this.navigate(_.toArray(arguments).join("/"), true);
},
reset: function() {
// Reset collections to initial state.
if (this.homepage) {
this.homepage.reset();
}
// Reset active model.
app.active = false;
}
});
return Router;
}
);
And here's my module:
define([
"app",
["localStorage"]
],
function(app){
"use strict";
var Homepage = app.module();
Homepage.Model = Backbone.Model.extend({
defaults: function(){
return {
homepage: {}
};
}
});
Homepage.Collection = Backbone.Collection.extend({
//localStorage: new Backbone.LocalStorage("Homepage.Collection"),
refreshFromServer: function() {
return Backbone.ajaxSync('read', this).done( function(data){
console.log(data);
//save the data somehow?
});
},
/*model: Homepage.Model,*/
cache: true,
url: '/app/json/test.json',
initialize: function(options){
if (options) {
this.homepage = options.homepage;
}else{
//this.refreshFromServer();
}
}
});
Homepage.Views.Index = Backbone.View.extend({
template: "homepage",
el: '#mainContent',
serialize: function() {
return {
collection: this.options.homepage
};
},
initialize: function(){
this.listenTo(this.options.homepage,{
"reset": this.render,
"fetch": function(){
$(this.el).html("Loading...");
}
});
}
});
return Homepage;
});
As you can see, the "main-frame" template is the main template that gets loaded into the page. I want the homepage template to load in afterwards, which gets populated into the id "#mainContent". In this case though, "#mainContent" doesn't exist yet so the homepage template isn't loaded in anywhere.
回答1:
This does not look right:
define([ // <- first bracket
"app",
["localStorage"] // <- second bracket
],
function(app){
...
Is it how it is in your code, or some copy-paste fluke?
回答2:
After much effort, I decided to move away from backbone-boilerplate, and now have the following setup using Backbone/RequireJS/localStorage adapter:
app.js:
define([
'jquery',
'underscore',
'backbone',
'router' // Request router.js
], function($, _, Backbone, Router){
var initialize = function(){
Router.initialize();
};
return {
initialize: initialize
};
});
main.js:
require.config({
paths: {
jquery: 'libs/jquery',
underscore: 'libs/underscore',
backbone: 'libs/backbone',
'backbone.localStorage': 'libs/backbone.localStorage',
templates: 'templates'
},
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ['underscore','jquery'],
exports: 'Backbone'
},
'backbone.localStorage': {
deps: ['backbone'],
exports: 'Backbone'
}
}
});
require([
'app'
], function(App){
App.initialize();
});
router.js:
define([
'jquery',
'underscore',
'backbone',
//Modules
"modules/homepage"
],
function ($, _, Backbone, Homepage) {
"use strict";
// Defining the application router, you can attach sub routers here.
var Router = Backbone.Router.extend({
routes:{
"":"index"
}
});
var initialize = function(){
var app_router = new Router;
app_router.on('route:index', function(){
// Call render on the module we loaded in via the dependency array
var collection = new Homepage.Collection();
var homepage;
collection.fetch({
success: function(){
if(collection.length === 0){
console.log('refreshing from server...');
collection.refreshFromServer({
success: function(data){
collection.add(data);
collection.invoke('save');
homepage = new Homepage.Views.Index({
collection: collection
}).render();
}
})
}else{
console.log('already loaded in localStorage...');
homepage = new Homepage.Views.Index({
collection: collection
}).render();
}
}
});
});
Backbone.history.start();
};
return {
initialize: initialize
};
}
);
homepage.js:
define([
"jquery",
"underscore",
"backbone",
"backbone.localStorage",
"text!templates/homepage.html"
],
function($, _, Backbone, localStorage, homepageTemplate){
"use strict";
var Homepage = { Views: {} };
Homepage.Model = Backbone.Model.extend({
defaults: function(){
return {
homepageData: {}
};
}
});
Homepage.Collection = Backbone.Collection.extend({
localStorage: new Backbone.LocalStorage("RGPData"),
refreshFromServer: function(options) {
return Backbone.ajaxSync('read', this, options);
},
url: 'json/test.json',
model: Homepage.Model
});
Homepage.Views.Index = Backbone.View.extend({
template:"homepage",
el: '#mainContent',
initialize: function(){
this.listenTo(this.collection, 'change', this.render);
this.listenTo(this.collection, 'destroy', this.remove);
},
render: function(){
console.log('rendering...');
$(this.el).html( homepageTemplate, this.collection);
return this;
}
});
return Homepage;
});
The way this works, I have the app use the localStorage adapter, while having a "refreshFromServer" in my collection to read from a JSON file if the localStorage is empty. The collection is fetched in the router, before inserted into the view.
This has been quite some time for me to discovery how everything works, so hopefully this answer will help anyone else out there get their footing a little bit better than I did.
A couple of notes, I use text.js in order to bring in the template.
Another note, I tried including backbone.localStorage and returning as just 'Backbone' (as depicted in http://kilon.org/blog/2012/08/build-backbone-apps-using-requirejs/), but for some reason that didn't work and my homepage.js file kept saying "Backbone.Model is not defined". Therefore I ended up including both in the define.
来源:https://stackoverflow.com/questions/14857166/view-loading-before-main-layout-is-loaded