我刚开始使用Backbone.我经历了前两个很棒的PeepCode截屏视频,现在我正在深入研究未来应用的快速分离(无服务器端)模拟.
这是我想要建立的(大致).一系列五个文本框 - 让我们调用这些小部件.选中后,每个窗口小部件输入将显示一个窗格,其中显示与窗口小部件关联的任务,并允许用户创建新任务或销毁现有任务.
在这一点上,我想我有以下模型:
Widget
Task
Run Code Online (Sandbox Code Playgroud)
以下集合:
Tasks
Widgets
Run Code Online (Sandbox Code Playgroud)
以下视图(这是多毛的地方!)
WidgetListView
- Presents a collection of Widgets
WidgetView
- sub-view of WidgetListView to render a specific Widget
TaskPaneView
- Presented when the user selects a Widget input
TaskCreateView
- Ability to create a new Task associated with selected Widget
TaskListView
- Presents a collection of Tasks for the given widget
TaskView
- Displays Task detail - sub-view of TaskListView
Run Code Online (Sandbox Code Playgroud)
假设这是合理的,那么当选择WidgetView时,技巧就变成了如何显示TaskPaneView.而且,TaskPaneView应该如何呈现TaskCreateViews和TaskListViews.
这里真正的问题是:一个级联是否跨视图呈现事件?Root视图是否允许知道子视图并显式呈现它们?这应该是事件驱动的吗?
抱歉,如果这是一个开放式的问题,只是希望有人以前会看到类似的东西,并能够指出我正确的方向.
谢谢!
Chr*_*rdi 15
绝对让它成为事件驱动.另外,尽量不要创建紧密耦合的视图.松散的耦合将使您的代码更易于维护和灵活.
查看关于事件聚合器模型和主干的这篇文章:
简短的版本是你可以这样做:
var vent = _.extend({}, Backbone.Events);
Run Code Online (Sandbox Code Playgroud)
并使用vent.trigger和vent.bind来控制你的应用程序.
Mos*_*man 12
Pre ps:我用你在下面写的代码为你做了一个要点:https: //gist.github.com/2863979
我同意其他答案所建议的pub/sub('观察者模式').然而,我也会使用Require.js和Backbone的强大功能.
Addy Osmani写了几篇很棒!有关Javascript设计模式和构建Backbone应用程序的资源:
http://addyosmani.com/resources/essentialjsdesignpatterns/book/ http://addyosmani.com/writing-modular-js/ http://addyosmani.github.com/backbone-fundamentals/
使用AMD(在Require.js中实现)以及Backbone的一个很酷的事情是你解决了一些你通常遇到的问题.
通常,您将以某种命名空间的方式定义类并存储它们,例如:
MyApp.controllers.Tasks = Backbone.Controller.extend({})
Run Code Online (Sandbox Code Playgroud)
这是好的,只要你在一个文件中定义的大多数事情,当你开始添加越来越多的不同的文件到它会不太可靠的搭配,你必须开始关注你在不同的文件如何加载,controllers\Tasks.js以后models\Task.js等你当然可以按正确的顺序编译所有文件等,但它远非完美.
除此之外,非AMD方式的问题在于您必须更紧密地将视图嵌套在彼此内部.让我们说:
MyApp.classes.views.TaskList = Backbone.View.extend({
// do stuff
});
MyApp.views.App = Backbone.View.extend({
el: '#app',
initialize: function(){
_.bindAll(this, 'render');
this.task_list = new MyApp.classes.views.TaskList();
},
render: function(){
this.task_list.render();
}
});
window.app = new MyApp.views.App();
Run Code Online (Sandbox Code Playgroud)
一切都很好,但这可能成为一场噩梦.
使用AMD,你可以定义一个模块并给它一些依赖,如果你对它的工作方式感兴趣,请阅读上面的链接,但上面的例子看起来像这样:
// file: views/TaskList.js
define([], function(){
var TaskList = Backbone.View.extend({
//do stuff
});
return new TaskList();
});
// file: views/App.js
define(['views/TaskList'], function(TaskListView){
var App = Backbone.View.extend({
el: '#app',
initialize: function(){
_.bindAll(this, 'render');
},
render: function(){
TaskListView.render();
}
});
return new App();
});
// called in index.html
Require(['views/App'], function(AppView){
window.app = AppView;
});
Run Code Online (Sandbox Code Playgroud)
请注意,在视图的情况下,您将返回实例,我也会为集合执行此操作,但对于模型,我将返回类:
// file: models/Task.js
define([], function(){
var Task = Backbone.Model.extend({
//do stuff
});
return Task;
});
Run Code Online (Sandbox Code Playgroud)
起初看起来可能有点多,人们可能会认为"哇这太过分了".但是当你必须在许多不同的模块中使用相同的对象时,真正的力量变得清晰,例如集合:
// file: models/Task.js
define([], function(){
var Task = Backbone.Model.extend({
//do stuff
});
return Task;
});
// file: collections/Tasks.js
define(['models/Task'], function(TaskModel){
var Tasks = Backbone.Collection.extend({
model: TaskModel
});
return new Tasks();
});
// file: views/TaskList.js
define(['collections/Tasks'], function(Tasks){
var TaskList = Backbone.View.extend({
render: function(){
_.each(Tasks.models, function(task, index){
// do something with each task
});
}
});
return new TaskList();
});
// file: views/statistics.js
define(['collections/Tasks'], function(Tasks){
var TaskStats = Backbone.View.extend({
el: document.createElement('div'),
// Note that you'd have this function in your collection normally (demo)
getStats: function(){
totals = {
all: Tasks.models.length
done: _.filter(Tasks, function(task){ return task.get('done'); });
};
return totals;
},
render: function(){
var stats = this.getStats();
// do something in a view with the stats.
}
});
return new TaskStats();
});
Run Code Online (Sandbox Code Playgroud)
请注意,'Tasks'对象在两个视图中完全相同,因此相同的模型,状态等等.这比在一个点上创建Tasks集合的实例然后通过整个应用程序引用它更好.时间.
至少对我来说,使用带有Backbone的Require.js已经带走了一个令人费解的巨大片段,在哪里实例化.使用模块非常有帮助.我希望这也适用于你的问题.
请注意,你也可以将Backbone,Underscore和jQuery作为模块添加到你的应用程序中,尽管你不必这样做,你可以使用普通的脚本标签加载它们.