默认情况下,从服务器获取数据是异步调用,那么为什么不使用命令而不是请求/响应并监听模型事件呢?我认为这会更容易。
在这个话题上,我会创建一个频道来提供,
- 获取数据的命令
- 通道应用的模型或集合实例。
然后控制器只需订阅通道以获取数据并监听集合实例事件(同步错误更改,无论您想要模型/集合上的任何基本主干事件)
/* Constants: Simulation of API data. */
Constants = {};
Constants.jsonLanguages = [
{Name: "English", Code: "en", isEditable:true},
{Name: "French", Code: "fr", isEditable:false},
{Name: "German", Code: "de", isEditable:true},
{Name: "Spanish", Code: "es", isEditable:false}
];
Constants.jsonBook = {
Title: "Dune",
AuthorName: "Frank Herbert",
LanguageCode: "en",
ISBN: "978-1-4493-9268-0"
};
/* ----------------------------------------------------------------------------- */
/* Models */
// Language/Models.js
var models = {};
models.Language = Backbone.Model.extend({
defaults: {
Name: "English",
Code: "en"
},
idAttribute:"Code",
url: "/echo/json/"
});
models.LanguageCollection = Backbone.Collection.extend({
model: models.Language,
url: "/echo/json/"
});
// Book/Models.js
models.Book = Backbone.Model.extend({
defaults: {
Title: "",
AuthorName: "",
Language: null
},
url: "/echo/json/",
idAttribute: "ISBN"
});
/* ----------------------------------------------------------------------------- */
/* Channels: Manage data between server and client.
- dependencies : wreqr, related models, related routes */
// Languages/Channel.js
var LanguageChannel = {};
LanguageChannel.data = {};
LanguageChannel.data.workingLanguage = new models.Language();
LanguageChannel.data.languages = new models.LanguageCollection();
LanguageChannel.channel = Backbone.Wreqr.radio.channel("Languages");
LanguageChannel.channel.commands.setHandler("getLanguages", function() {
// here you typically fetch the data using backbone collection and backbone router
window.console && console.log("LanguageChannel.channel.command.getLanguages()");
LanguageChannel.data.languages.reset(Constants.jsonLanguages);
LanguageChannel.data.languages.trigger("sync");
});
// Books/Channel.js
var BookChannel = {};
BookChannel.data = {};
BookChannel.data.book = new models.Book();
BookChannel.channel = Backbone.Wreqr.radio.channel("Books");
BookChannel.channel.commands.setHandler("getBook", function(id){
// here you typically fetch the data using backbone model & backbone router
window.console && console.log("BookChannel.channel.commands.getBook(" + id +")");
BookChannel.data.book.set(Constants.jsonBook, {reset:true});
BookChannel.data.book.trigger("sync");
});
/* ----------------------------------------------------------------------------- */
/* Views: Manage template and view events. */
// Book/Views.js
BookAttributesView = Marionette.ItemView.extend({
el: "#BookAttributesBox",
template: "#BookAttributesTemplate",
bindings:
{
"#Title": "Title",
"#AuthorName": "AuthorName",
"#LanguageCode": {
observe: "LanguageCode",
selectOptions: {
collection: LanguageChannel.data.languages,
labelPath: "Name",
valuePath: "Code"
},
update: function($el, val, model, options) {
window.console && console.log("View.bindings.#LanguagageCode:update");
LanguageChannel.data.languages.each(function(language){
// Find parent.
var parent = $el.find("#LanguageReadable");
if (language.get("isEditable")){
parent = $el.find("#LanguageEditable");
}
// Select correct value.
var selected = "";
if (language.get("Code") == val){
selected = ' selected="selected"';
}
// Add option to optgroup.
parent.append("<option" + selected + ">" + language.get("Name") + "</option>");
});
}
}
},
onRender: function () {
window.console && console.log("View.onRender");
this.stickit();
}
});
/* ----------------------------------------------------------------------------- */
/* Controllers: Manage page behaviour. */
// Books/Controller.js:
BookController = Marionette.Controller.extend({
initialize: function(){
window.console && console.log("Controller.ctor");
var self = this;
self.bookId = "978-1-4493-9268-0"
// Callbacks from data channels.
self.listenTo(LanguageChannel.data.languages, "sync", self.onSyncLanguages);
self.listenTo(BookChannel.data.book, "sync", self.onSyncBook);
// Retrieve data.
LanguageChannel.channel.commands.execute("getLanguages");
BookChannel.channel.commands.execute("getBook", self.bookId);
},
/* Book functions */
onSyncBook: function(){
window.console && console.log("Controller.onSyncBook");
this.showBookAttributes(); // TODO, use : LanguageChannel.data.languages.fetch();
},
showBookAttributes: function(){
window.console && console.log("Controller.showBookAttributes");
new BookAttributesView({ model: BookChannel.data.book }).render();
},
/* Language functions */
onSyncLanguages: function(){
window.console && console.log("Controller.onSyncLanguages")
this.showBookAttributes();
}
});
/* ----------------------------------------------------------------------------- */
/* Aplication.js: Starts the backbone application (main entry point). */
// Book/Application.js
Application = Marionette.Application.extend({
onStart: function(){
window.console && console.log("Application.start()");
new BookController();
}
});
fiddle link 展示如何做——当然,在你的项目中,你需要“要求你的几个模块”。
fiddle 链接基于 C0b0ll - 实际上,一位同事 - 在 stickit usage-yes another jsFiddle link 上做的
这样做,控制台将记录以下内容:
- Application.start()
- Controller.ctor
- LanguageChannel.channel.command.getLanguages()
- Controller.onSyncLanguages
- Controller.showBookAttributes
- View.onRender
- View.bindings.#LanguagageCode:update
- BookChannel.channel.commands.getBook(978-1-4493-9268-ø)
- View.bindings.#LanguagageCode:update
- Controller.onSyncBook
- Controller.showBookAttributes
- View.onRender
- View.bindings.#LanguagageCode:update