我正在使用rails 3.1 mongodb和backbonejs构建小型单页应用程序。
我有两个资源可以通过json api获得。我在骨干中创建了两个模型和集合,看起来像这样
https://gist.github.com/1522131
我也有两个独立的路由器
项目路由器 - https://gist.github.com/1522134 注意路由器 - https://gist.github.com/1522137
我使用github的backbonejs-rails gem生成它们,所以内部的代码只是模板。我在index.haml文件中初始化我的基本路由器
#projects
:javascript
$(function() {
window.router = new JsonApi.Routers.ProjectsRouter({projects: #{@projects.to_json.html_safe}});
new JsonApi.Routers.NotesRouter();
Backbone.history.start();
});
我不希望在应用程序启动时获取备注,因为用户很可能永远不会查看备注内容。所以没有充分的理由在开始时获取它。在NotesRouter里面的所有动作我都依赖于@notes变量但没有.fetch()方法这个变量是空的。另外我应该可以从网址中重现笔记视图
/ 1 / notes / 5
project_id = 1 note_id = 5
什么是backbonejs解决此类问题的最佳做法?
答案 0 :(得分:2)
为什么不在请求时懒惰加载笔记?这是一个例子:
var State = Backbone.Model.extend({
defaults: {
ready: false,
error: null
}
});
var Note = Backbone.Model.extend({
initialize: function () {
this.state = new State();
}
});
var Notes = Backbone.Collection.extend({
model: Note,
initialize: function () {
this.state = new State();
}
});
var NoteCache = Backbone.Model.extend({
initialize: function () {
this._loading = false;
this._loaded = false;
this._list = new Notes();
},
_createDeferred: function (id) {
var note = new Note({ id: id });
this._list.add(note);
this._load();
return note;
},
getNote: function (id) {
return this._list.get(id) || this._createDeferred(id);
},
getNotes: function () {
if (!this._loaded)
this._load();
return this._list;
},
_load: function () {
var that = this;
if (!this._loading) {
this._list.state.set({ ready: false, error: null });
this._loading = true;
$.ajax({
url: '/api/notes',
dataType: 'json',
cache: false,
type: 'GET',
success: function (response, textStatus, jqXHR) {
_.each(response.notes, function (note) {
var n = that._list.get(note.id);
if (n) {
n.set(note);
} else {
that._list.add(note, { silent: true });
n = that._list.get(note.id);
}
n.state.set({ ready: true, error: null });
});
that._list.state.set({ ready: true, error: null });
that._list.trigger('reset', that._list);
that._loaded = true;
},
error: function (jqXHR, textStatus, errorThrown) {
that._list.state.set({ error: 'Error retrieving notes.' });
that._list.each(function (note) {
note.state.set({ error: 'Error retrieving note.' });
});
},
complete: function (jqXHR, textStatus) {
that._loading = false;
}
});
}
}
});
在这个例子中,我正在定义一个管理延迟加载的NoteCache对象。我还在Note模型和Notes集合中添加了“state”属性。
你可能想要在某个地方(可能在你的路线内)初始化NoteCache,并且只要你想要一个音符或音符,就这样做:
var note = noteCache.getNote(5);
var notes = noteCache.getNotes();
现在在你的视图中,如果还没有加载音符/音符,你会想要听取状态变化:
var NoteView = Backbone.View.extend({
initialize: function(){
this.note.state.bind('change', this.render, this);
},
render: function(){
if (this.note.state.get('error') {
// todo: show error message
return this;
}
if (!this.note.state.get('ready') {
// todo: show loader animation
return this;
}
// todo: render view
return this;
}
});
我没有对此进行过测试,因此可能存在一些错误,但我希望您明白这一点。