【问题标题】:structuring AngularJS application构建 AngularJS 应用程序
【发布时间】:2013-05-20 16:35:48
【问题描述】:

我们有一个相当大的 angularJS 应用程序,其中所有控制器都在一个文件中。

我们正在考虑将每个控制器拆分为相应的文件。有什么不做的理由吗?

我们想要拆分它的原因是因为更容易管理文件中的源代码控制/更改,而且显然更直观。

请指教。

【问题讨论】:

    标签: angularjs file-structure


    【解决方案1】:

    在我看来,构建 大型 AngularJS 应用程序的最佳方式是按照 Peter Bacon Darwin 和 Pawel Kozlowski 在他们的《Mastering Web使用 AngularJS 开发应用程序”。

    与 AngularJS 种子项目(以及许多其他项目,如 Yeoman 的 generator-angular)推荐的结构不同,“技术驱动”意味着每个元素类型,如控制器、部分/视图等。在其自己的文件夹中,您应该使用“域驱动”结构,它反映了代码中的业务域

    它有很多优点,例如:

    • 使代码的所有权明确明确,
    • 引入了在所有模块之间共享的通用语言,
    • 授权(在一定程度上)与业务分析师直接沟通,
    • 消除了潜在的冲突,因为对合并等的需求较低。

    这里是上面提到的书中提出的结构的示例(只是为了澄清想法):

    项目中的顶级目录:

    - src: contains application source code
    - test: contains accompanying automated tests
    - vendor: contains third party dependencies
    - build: contains build scripts
    - dist: contains build results, ready to be deployed in a target environment
    

    src文件夹内(固定):

    - app: AngularJS-specific code, domain-driven
    - common: AngularJS-specific code, boiler-plate
    - assets: holds images and icons,
    - less: LESS variables
    - index.html - entry point to the application
    

    app 文件夹内(域驱动),例如网上商店:

    - shop
      - products
      - customers
      - orders
        - orderlists
        - orderdetails
        - ... etc.
    - admin
      - users
      - ... etc.
    

    每个文件夹都包含所有相关代码,包括部分、脚本等。

    【讨论】:

    • 感谢您的建议。但也请尝试回答这个问题,有什么理由不这样做吗?
    • 你有特征结构的例子吗?
    • @pal4life 好问题。就我个人而言,我在每个项目中都使用 by feature 结构。但是,为此,您需要对您计划实现的域模型有一个很好的概述。如果您的需求集非常不清楚,并且您期望在开发过程中进行大量更改和重构(例如,由于用户的反馈),我会坚持更多技术驱动的结构。作为域驱动的,它将变得简单“更稳定”。
    • @Matsemann 刚刚更新了我上面的答案。我希望这个想法现在很清楚。
    • @AdamBoczek 谢谢,我现在明白你的意思了。
    【解决方案2】:

    来自an article by Brian Ford

    对于大型应用程序来说,最大的问题可能是把所有的 那个代码。在你的组织工具的工具带上,你有文件, 目录、模块、服务和控制器。快速概览 好的 AngularJS 项目结构,查看 Angular 种子 GitHub。但是我想更深入一点并提供一些 关于项目结构的额外建议。让我们从目录开始 并按照我们的方式完成列表。

    例如你的文件结构可以是这样的:

    project/
           app.js
           controllers/ #your controllers files here
           views/  #your templates here
           services/  #your services files
           directives/ #your custom directives
    

    每个文件都应该有一个“事物”,其中“事物”是 控制器、指令、过滤器或服务。这使得小, 重点文件。它还有助于为 API 如何创建一个试金石 正在做。如果您发现自己也来回翻阅文件 通常,这表明您的 API 过于复杂。你 应该重新思考、重构和简化。

    查看文章了解更多详情。

    【讨论】:

    • 您的链接在这里不起作用。还有一些关于为什么的说明,你建议你做什么会很好。编辑,链接现在有效。
    • 这对我来说似乎是一个很好的答案。 @Or-a 您应该考虑接受它或发布一些关于您认为缺乏的内容。
    【解决方案3】:

    您可以通过多种不同的方式来构建应用程序,而且几乎没有对错之分。所以不,没有理由不这样做,看起来它是有道理的。

    根据我的经验,我个人决定使用以下结构给你一个例子:

    我使用Angular Seed Project的目录结构:

    • app/js -> 包含所有动态js脚本
    • app/lib/angular114 -> 包含当前的 angularjs 版本(我可以通过这种方式使用多个版本进行测试)
    • app/lib/mycompany -> 包含我保存在单独存储库中的所有公司/个人可重用库
    • app/partials -> 包含我所有的 html 部分,我根据 app/js 中的 js 文件结构划分到子目录中。如果我有一个 user.js,那么我就有一个用户目录。

    自己的库

    在我自己的位于 lib/mycompany 的库中,我为所有文件和方法名称加上我的公司前缀。如果我的公司将被称为东亚有限公司,那么我将创建一个名为“ea”的两个字母前缀。这将防止名称与我的动态 js 脚本发生冲突,因为控制器和服务的名称可以通过我的应用程序公开。

    lib/ea/ea-validators.js

    (function() {
      'use strict'
      angular.module('eaValidators', [])
        .directive('eaValidateUnique', [function() {
          // directive code goes here
        }])
        .directive('eaValidateId', [function() {
          // code goes here
        }])
        .controller('MyCtrlJustAsExample', ['$scope', function($scope) {
          // code goes here
        }]);    
    })();
    

    我将所有内容分组到逻辑模块中,例如:

    • 验证模块
    • 全局错误处理模块
    • 认证/授权模块
    • ...

    例如,身份验证模块包含指令、控制器、服务等。我区分逻辑实体,而不是区分控制器、指令等。我发现这种结构更有效,因为当我想更改例如与验证相关的内容时,我知道它在我的验证模块中。

    您可以在此处找到示例:http://chstrongjavablog.blogspot.ch/

    动态内容

    我的动态 js 文件有类似的方法。例如,如果我想要显示一个用户页面和一个供应商页面,那么我会在我的 js 目录中创建以下文件:

    • user.js
    • vendor.js

    同样,这些文件可以在同一文件中包含指令、控制器、服务,这些文件分组在一个模块下。因此,如果我需要更改与用户相关的内容,我会立即知道我会在 user.js 中找到代码。

    示例 user.js 可能如下所示:

    js/user.js

    angular.module('user', ['ngResource'])
      .controller('UserListCtrl', ['$scope', 'User', function($scope, User) {
         // code goes here
      }])
      .controller('UserNewCtrl', ['$scope', 'User', function($scope, User) {
        // code goes here
      }])
     .factory('User', ['$resource', function($resource) {
        return $resource('/api/user/:userId', {userId: '@id'});
     }]);       
    

    把它们粘在一起

    js/app.js

    然后我使用 js/app.js 将所有内容粘合在一起并进行路由:

    angular.module('myApp', ['eaValidators', 'vendor', 'user'])
      .config(['$routeProvider', function($routeProvider) {
        $routeProvider.when('/user', {templateUrl: 'partials/user/user-list.html', controller: 'UserListCtrl'});
        $routeProvider.when('/user/new', {templateUrl: 'partials/user/user-new.html', controller: 'UserNewCtrl'});
        $routeProvider.otherwise({redirectTo: '/user'});
    }])
      .config(['$httpProvider', function ($httpProvider) {
        $httpProvider.defaults.headers.common['Content-Type'] = 'application/json';
        $httpProvider.defaults.headers.common['Accept'] = 'application/json';
    }]);
    

    然后我只是在主 index.html 文件中挂钩文件:

    index.html

    <!doctype html>
    <html lang="en" ng-app="myApp">
    <head>
      <meta charset="utf-8">
      <title>YourApp</title>
      <link rel="stylesheet" href="css/app.css"/>
      <link rel="stylesheet" href="css/style.css"/>
      <link rel="stylesheet" href="css/ea-validators.css"/>
    </head>
    <body>
    
      <!-- Display partial pages -->
      <div ng-view></div>
    
      <!-- Include all the js files. In production use min.js should be used -->
      <script src="lib/jquery203/jquery-2.0.3.js"></script>
      <script src="lib/angular114/angular.js"></script>
      <script src="lib/angular114/angular-resource.js"></script>
      <script src="lib/ea/ea-validators.js"></script>
      <script src="js/app.js"></script>
      <script src="js/user.js"></script>
      <script src="js/vendor.js"></script>
    </body>
    </html>
    

    这种结构的好处是我可以将例如 user.js 和用户部分复制到另一个项目中并重复使用大部分代码。

    我还有我的全局验证处理程序、错误处理程序、身份验证处理程序,我可以从我的存储库中签出到 lib 目录。

    我发现这种结构是迄今为止最有效的。

    另一种方法

    您也可以使用 YeoMan,它对您的结构有很大帮助。然而,它确实添加了很多依赖项,当我尝试使用它时,我在安装过程中遇到了一些依赖冲突的问题。我个人的经验法则是,如果我不能在 1 天内完成某项工作,我会把手从它身上移开,因为我会浪费时间花在代码上。我给自己设定的另一条经验法则是,如果有一个由具有不同目标的个人开发的依赖项拼凑在一起的框架,我会尽可能避免它。请注意,这些是我自己制定的个人规则,可能不适合其他人。出于这些原因,我决定不使用它。但似乎已经有一个相当大的社区。

    生产

    出于生产目的,您可以使用 UglyfyJS 或 Google Closure Compiler 创建一个压缩的 js 文件,其中包含所有代码或每个文件单独压缩。

    我希望这个描述对你有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-21
      • 2012-12-09
      • 1970-01-01
      • 1970-01-01
      • 2012-07-02
      • 1970-01-01
      • 1970-01-01
      • 2015-01-14
      相关资源
      最近更新 更多