我使用yeoman generator-bbb在我的网站上创建了一个小应用程序。问题是集合视图不会更新。
这是主要代码: app.js:
define(function(require, exports, module) {
// External dependencies.
var _ = require("underscore");
var $ = require("jquery");
require("modernizr");
var Backbone = require("backbone");
var LayoutManager = require("backbone.layoutmanager");
require("plugins/backbone.collectioncache");
require("bootstrap-jam");
var app = module.exports = {};
// Path Backbone fetching to emmit a "fetch" event
Backbone.Collection.prototype.fetch = function() {
var fetch = Backbone.Collection.prototype.fetch;
return function() {
this.trigger("fetch");
return fetch.apply(this, arguments);
};
}();
// The root path to run the application through.
app.root = "/";
// Configure LayoutManager with Backbone Boilerplate defaults.
LayoutManager.configure({
// Allow LayoutManager to augment Backbone.View.prototype.
manage: true,
// Indicate where templates are stored.
prefix: "app/templates/",
// This custom fetch method will load pre-compiled templates or fetch them
// remotely with AJAX.
fetch: function(path) {
// Concatenate the file extension.
path = path + ".html";
// If cached, use the compiled template.
if (window.JST && window.JST[path]) {
return window.JST[path];
}
// Put fetch into `async-mode`.
var done = this.async();
// Seek out the template asynchronously.
$.get(app.root + path, function(contents) {
done(_.template(contents));
}, "text");
}
});
// The application user interface handles link hijacking and can be modified
// to handle other application global actions as well.
app.ui = new Backbone.View({
el: "#layout",
template: "main-layout",
events: {
"click a[href]:not([data-bypass])": "hijackLinks"
},
hijackLinks: function(ev) {
// Get the absolute anchor href.
var $link = $(ev.currentTarget);
var href = {
prop: $link.prop("href"),
attr: $link.attr("href")
};
// Get the absolute root.
var root = location.protocol + "//" + location.host + app.root;
// Ensure the root is part of the anchor href, meaning it's relative.
if (href.prop.slice(0, root.length) === root) {
// Stop the default event to ensure the link will not cause a page
// refresh.
ev.preventDefault();
// `Backbone.history.navigate` is sufficient for all Routers and will
// trigger the correct events. The Router's internal `navigate` method
// calls this anyways. The fragment is sliced from the root.
Backbone.history.navigate(href.attr, true);
}
}
});
});
router.js
define(function(require, exports, module) {
var app = require("app");
var Music = require("modules/music");
// Defining the application router.
module.exports = Backbone.Router.extend({
initialize: function() {
var collections = {
musics: new Music.Collection()
};
_.extend(this, collections);
app.ui.setViews({
".musics": new Music.Views.List(collections)
}).render();
},
routes: {
"": "index",
"tag/:name": "tag"
},
index: function() {
this.reset();
},
tag: function(name) {
this.reset();
this.musics.tag = name;
this.musics.fetch();
},
reset: function() {
if (this.musics.length) {
this.musics.reset();
}
},
go: function() {
return this.navigate(_.toArray(arguments).join("/"), true);
}
});
});
music.js:
define(function(require, exports, module) {
// music module dependedn on app
var app = require("app"),
Music = module.exports = {};
Music.Collection = Backbone.Collection.extend({
url: function() {
return "https://api.douban.com/v2/music/search?tag=" + encodeURIComponent(this.tag) + "&callback=?";
},
cache: true,
parse: function(res) {
if ( res.musics.length ) {
this.status = "valid";
return res.musics;
}
this.status = "invalid";
return res;
},
initialize: function(models, options) {
if (options) {
this.tag = options.tag;
}
}
});
Music.Views = {};
// set the list view
Music.Views.List = Backbone.View.extend({
template: "music/list",
serialize: function() {
return { collection: this.options.musics };
},
events: {
"submit form": "updateMusic"
},
updateMusic: function() {
app.router.go( "tag", this.$('form').find('input').val() );
return false;
},
beforeRender: function() {
this.options.musics.each(function(music) {
this.insertView("ul", new Music.Views.Item({
model: music
}));
}, this);
},
afterRender: function() {
this.$("input.invalid").focus();
},
initialize: function() {
this.listenTo(this.options.musics, {
"reset": this.render,
"fetch": function() {
this.$("ul").parent().html("搜索中请稍候......");
}
});
}
});
// set the item view
Music.Views.Item = Backbone.View.extend({
template: "music/item",
tagName: "li",
serialize: function() {
return { model: this.model };
},
initialize: function() {
this.listenTo( this.model, "change", this.render() );
}
});
});
答案 0 :(得分:0)
看起来您正在提出跨域请求。您已设置url
,以便接受回调。现在无处允许Backbone知道这是jsonp
请求。
尝试将dataType: 'jsonp'
属性传递给获取请求。
tag: function(name) {
this.reset();
this.musics.tag = name;
this.musics.fetch({
dataType : 'jsonp'
});
},
而且我也没有看到在你所指的
视图中的任何地方定义的2个方法"reset": this.render,
this.insertView("ul",