大backbone.js网页应用程序组织

我目前正在构build一个基于backbone.js的大型web应用程序,并且在组织,“僵尸”等方面遇到了很多问题,所以我决定做一个重要的代码重构。 我已经写了一堆处理“僵尸”的辅助函数。 不过,我想从头开始,并创build一个很好的结构/组织的代码。 我还没有find关于大规模backbone.js组织的很多很好的教程/例子,所以我从头开始,想看看我能否从我开始的地方得到一些意见。

我明显在全局命名空间中设置我的代码; 但我也想保持这个名字空间相当干净。 我的主app.js保持类文件本身与全局名称空间分开; 你可以通过使用reg()函数注册一个类(这样它可以被实例化),而inst()函数实例化类数组中的一个类。 因此,除了3个方法之外,MyApp命名空间只有Router,Model和View:

var MyApp = (function () { var classes = { Routers: {}, Collections: {}, Models: {}, Views: {} }; methods = { init: function () { MyApp.Router = MyApp.inst('Routers', 'App'); MyApp.Model = MyApp.inst('Models', 'App'); MyApp.View = MyApp.inst('Views', 'App'); Backbone.history.start(); }, reg: function (type, name, C) { classes[type][name] = C; }, inst: function (type, C, attrs) { return new classes[type][C](attrs || {}); } }; return methods; }()); $(MyApp.init); 

在模型,集合,路由器和视图中,我照常工作,但是需要在文件的末尾注册该类,以便在稍后的时间点(不会混淆命名空间)实例化:

 MyApp.reg('Models', 'App', Model); 

这似乎是不必要的方式来组织代码? 其他人是否有更好的例子来说明如何用许多路由器,集合,模型和视图组织真正的大型项目?

我最近在一个名为GapVis的Backbone项目上工作( 这里的代码,这里 呈现的内容 )。 我不知道它是否“真的很大”,但它是大而复杂的 – 24视图类,5路由器等。这可能是值得一看,但我不知道我所有的方法将是相关。 你可以在我的主app.js文件中看到我的一些想法。 几个关键的架构select:

  • 我有一个包含所有当前状态信息的单State模型 – 当前视图,我们正在查看的模型ID等等。每个需要修改应用程序状态的视图都通过在状态上设置属性以及需要的每个视图回应国家倾听该模型的事件。 对于修改状态和更新的视图来说,情况更是如此 – 事件中的UI事件处理程序从不重新渲染视图,而是通过将渲染函数绑定到状态来完成。 这种模式确实有助于保持视图彼此分离 – 视图从不会在另一个视图上调用方法。

  • 我的路由器被视为专门的视图 – 它们通过更新状态来响应UI事件(即inputURL),并通过更新UI(即更改URL)来响应状态更改。

  • 我做了几件与你的build议类似的事情。 我的命名空间有一个类似于你的init函数,还有一个常量settings对象。 但是我把大部分模型和视图类都放在了命名空间中,因为我需要在多个文件中引用它们。

  • 我为我的路由器使用注册系统,并为我的视图考虑一个注册系统,作为让“主”类( AppRouterAppView )不必知道每个视图的好方法。 然而,在AppView案例中,结果是子视图的顺序很重要,所以我最终对这些类进行了硬编码。

我很难说这是做事的“正确”方式,但对我来说却是有效的。 我希望这是有帮助的 – 我也很难find使用Backbone的大型项目的可见源示例,并且在我走的时候不得不解决大部分的问题。

这两个资源帮助我在坚实的地下室里安装我的骨干应用程序:

我命名空间类似于你正在做的(至less对于类的一部分),我所有的模型,视图和控制器如下所示:

意见/ blocks.js:

 (function(cn){ cn.classes.views.blocks = cn.classes.views.base.extend({ events: {}, blocksTemplate: cn.helpers.loadTemplate('tmpl_page_blocks'), initialize: function(){ }, render: function(){ $(this.el).html(this.blocksTemplate()); }, registerEvents: function(){}, unregisterEvents: function(){} }); })(companyname); 

我的JavaScript命名空间看起来像这样,但我每次构build新的应用程序时都会改进它:

  companyname:{ $: function(){}, <== Shortcut reference to document.getElementById appView: {}, <== Reference to instantiated AppView class. classes = { <== Namespace for all custom Backbone classes. views : {}, models : {}, collections: {}, controllers : {}, Router: null }, models: {}, <== Instantiated models. controllers: {}, <== Instantiated controllers. router: {}, <== Instantiated routers. helpers: {}, <== Reusable helper platform methods. currentView: {}, <== A reference to the current view so that we can destroy it. init: function(){} <== Bootstrap code, starts the app. } 

任何我想我所有的观点都有,我放在基本观点上。 我的控制器会在它创build的任何新视图上(调用render之后)调用registerEvents ,并在视图之前closures视图上的unregisterEvents 。 并不是所有的视图都有这两个额外的方法,所以它首先检查存在。

不要忘记,所有的意见都与一个this.el.remove(); 它不仅杀死视图容器元素,而且还解除绑定到它的所有事件。 根据你通过你的控制器创build视图的方式,你可能并不想杀死这个元素,而是使用this.el.unbind()来解除所有的事件。

实际上,不同的方式有不同的优缺点。最重要的是要find一个合适的文件组织方式。以下是我目前正在做的项目的组织结构。 这样焦点将是相同的模块相关的文件被放置在一个文件夹中。 例如:人员模块,这个模块的所有文件都放在modules / base / people目录下。 在更新和维护这个模块之后,只需要把重点放在这个目录下的文件就行了,不会影响目录外的文件,并且提高了可维护性。

希望我的回答能给你一些帮助,希望你们有一些宝贵的意见。

在这里输入图像说明