大型backbone.js网络应用程序组织

时间:2011-11-03 22:40:49

标签: javascript jquery namespaces backbone.js organization

我目前正在开发一个基于backbone.js构建的大型网络应用程序,并且在组织,“僵尸”等方面遇到了很多问题。所以我决定做一个主要的代码重构。我已经编写了一堆辅助函数来处理“僵尸”;但是,我想从一开始就为代码创建一个很好的结构/组织。我没有在大型的backbone.js组织上找到很多很棒的教程/例子,所以我从头开始,想看看我是否可以就我开始的地方得到一些意见。

我显然在全局命名空间中设置了我的代码;但我也想保持这个命名空间相当干净。我的主要app.js使类文件本身与全局命名空间分开;您可以使用reg()函数注册一个类(以便可以实例化它),而inst()函数可以从classes数组中实例化一个类。因此,除了3种方法之外,MyApp命名空间只有路由器,模型和视图:

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);

在模型,集合,路由器和视图中,我像往常一样工作,但是然后需要在文件的末尾注册该类,以便可以在以后实例化它(不会使命名空间混乱): p>

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

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

4 个答案:

答案 0 :(得分:32)

我最近参与了一个名为GapVis(code hererendered content here)的Backbone项目。我不知道它是否“非常大”,但它是大而且相对复杂 - 24个视图类,5个路由器等等。虽然我不知道我的所有方法都是相关。你可以在main app.js file的长篇介绍评论中看到我的一些想法。一些关键的架构选择:

  • 我有一个单独的State模型,它包含所有当前状态信息 - 当前视图,我们正在查看的模型ID等等。每个需要修改应用程序状态的视图都通过设置来完成State上的属性,每个需要响应状态的视图都会侦听该模型的事件。对于修改状态和更新的视图尤其如此 - events中的UI事件处理程序永远不会重新呈现视图,而是通过将呈现函数绑定到状态来完成。这种模式确实有助于保持视图彼此分离 - 视图从不在另一个视图上调用方法。

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

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

  • 我为我的路由器使用注册系统,并将其视为我的视图,这是保持“主”类(AppRouterAppView)的一种好方法意识到每一个观点。然而,在AppView案例中,结果显示子视图的顺序非常重要,因此我最终对这些类进行了硬编码。

我很难说这是做事的“正确”方式,但它对我有用。我希望这很有帮助 - 我也很难找到使用Backbone的大型项目的可见源代码示例,并且在我进行过程中不得不解决大部分问题。

答案 1 :(得分:13)

这2个资源帮助我在坚实的基础上设置我的骨干应用程序:

答案 2 :(得分:5)

我的命名空间类似于你正在做的事情(至少对于类部分而言),我的所有模型,视图和控制器都是这样的:

视图/ 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命名空间看起来像这样,但每次构建新应用程序时我都会改进它:

 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.                                                                                                                           
 } 

我希望我的所有观点都有,我把它放在基本视图中。我的控制器将在它创建的任何新视图(渲染后)上调用registerEvents,并在视图杀死之前调用unregisterEvents。并非所有视图都有这两个额外的方法,所以它首先检查是否存在。

不要忘记所有视图都内置了this.el.remove();。这不仅会杀死视图容器元素,还会取消绑定附加到它的所有事件。根据您通过控制器创建视图的方式,您可能实际上不想杀死该元素并执行this.el.unbind()而不是取消绑定所有事件。

答案 3 :(得分:5)

事实上,以不同的方式有不同方式的优点和缺点。最重要的是找到一种合适的文件组织方式。以下是我目前正在进行的项目的组织。这种方式的重点是将相同的模块相关文件放在一个文件夹中。例如:people模块,这个模块的所有文件都放在modules / base / people目录下。更新和维护这个模块后,只需要关注这个目录中的文件就行了,不会影响目录外的文件,提高了可维护性。

我希望我的回答可以给你一些帮助,我希望你有一些宝贵的建议。

enter image description here