116

我在我的应用程序中声明了一堆 Angular 模块。我最初开始使用这样的“链式”语法来声明它们:

angular.module('mymodule', [])
    .controller('myctrl', ['dep1', function(dep1){ ... }])
    .service('myservice', ['dep2', function(dep2){ ... }])
    ... // more here

但我认为这不是很容易阅读,所以我开始使用这样的模块变量声明它们:

var mod = angular.module('mymodule', []);

mod.controller('myctrl', ['dep1', function(dep1){ ... }]);

mod.service('myservice', ['dep2', function(dep2){ ... }]);
...

第二种语法对我来说似乎更具可读性,但我唯一的抱怨是这种语法将mod变量留在了全局范围内。如果我有其他一些名为 的变量mod,它将被下一个(以及与全局变量相关的其他问题)覆盖。

所以我的问题是,这是最好的方法吗?或者做这样的事情会更好吗?:

(function(){
    var mod = angular.module('mymod', []);
    mod.controller('myctrl', ['dep1', function(dep1){ ... }]);
    mod.service('myservice', ['dep2', function(dep2){ ... }]);
    ...
})();

或者它甚至足以关心?只是想知道模块声明的“最佳实践”是什么。提前致谢。

4

7 回答 7

118

声明模块的“最佳”方式

由于 Angular 本身位于全局范围内,并且模块被保存到其变量中,您可以通过以下方式访问模块angular.module('mymod')

// one file
// NOTE: the immediately invoked function expression 
// is used to exemplify different files and is not required
(function(){
   // declaring the module in one file / anonymous function
   // (only pass a second parameter THIS ONE TIME as a redecleration creates bugs
   // which are very hard to dedect)
   angular.module('mymod', []);
})();


// another file and/or another anonymous function
(function(){   
 // using the function form of use-strict...
 "use strict";
  // accessing the module in another. 
  // this can be done by calling angular.module without the []-brackets
  angular.module('mymod')
    .controller('myctrl', ['dep1', function(dep1){
      //..
    }])

  // appending another service/controller/filter etc to the same module-call inside the same file
    .service('myservice', ['dep2', function(dep2){ 
    //... 
    }]);

  // you can of course use angular.module('mymod') here as well
  angular.module('mymod').controller('anothermyctrl', ['dep1', function(dep1){
      //..
  }])
})();

不需要其他全局变量。

当然,这完全取决于偏好,但我认为这是最好的做法,因为

  1. 你不必污染全局范围
  2. 您可以在任何地方访问您的模块,并随意将它们及其功能分类到不同的文件中
  3. 你可以使用“use strict”的函数形式;
  4. 文件的加载顺序并不重要

用于对模块和文件进行排序的选项

这种声明和访问模块的方式使您非常灵活。您可以通过函数类型(如另一个答案中所述)或通过路由对模块进行排序,例如:

/******** sorting by route **********/    
angular.module('home')...
angular.module('another-route')...
angular.module('shared')...

你最终如何排序取决于个人品味以及项目的规模和类型。我个人喜欢将模块的所有文件分组在同一个文件夹中(排序到指令、控制器、服务和过滤器的子文件夹中),包括所有不同的测试文件,因为它使您的模块更可重用。因此,在中型项目中,我最终得到一个基本模块,其中包括所有基本路由及其控制器、服务、指令和或多或少复杂的子模块,当我认为它们也可能对其他项目有用时,例如:

/******** modularizing feature-sets **********/
/controllers
/directives
/filters
/services
/my-map-sub-module
/my-map-sub-module/controllers
/my-map-sub-module/services
app.js
...

angular.module('app', [
  'app.directives',
  'app.filters',
  'app.controllers',
  'app.services',
  'myMapSubModule'
]);

angular.module('myMapSubModule',[
   'myMapSubModule.controllers',
   'myMapSubModule.services',
   // only if they are specific to the module
   'myMapSubModule.directives',
   'myMapSubModule.filters'
]);

对于非常大的项目,我有时最终会按路线对模块进行分组,如上所述,或者按一些选定的主要路线,甚至是路线和一些选定组件的组合,但这真的取决于。

编辑: 仅仅因为它是相关的,我最近又遇到了这个问题:注意只创建一次模块(通过向 angular.module-function 添加第二个参数)。这会弄乱您的应用程序并且很难检测到。

2015 年关于排序模块的编辑: 一年半的角度经验后,我可以补充一点,在您的应用程序中使用不同命名的模块的好处是有限的,因为 AMD 仍然不能很好地与 Angular 和服务、指令和过滤器配合使用无论如何,在角度上下文中都是全局可用的(如这里所示)。尽管如此,仍然存在语义和结构上的好处,并且能够包含/排除带有注释的单行代码的模块可能会有所帮助。

按类型(例如'myMapSubModule.controllers')分隔子模块几乎没有多大意义,因为它们通常相互依赖。

于 2013-11-13T15:17:18.547 回答
28

我喜欢 Johnpapa 的angular-styleguide,这里有一些与这个问题相关的规则:

规则:命名函数与匿名函数

避免使用匿名函数:

// dashboard.js
angular
  .module('app')
  .controller('Dashboard', function() { })

相反,使用命名函数:

// dashboard.js
angular
  .module('app')
  .controller('Dashboard', Dashboard);

function Dashboard() { }

正如作者所说:This produces more readable code, is much easier to debug, and reduces the amount of nested callback code.

规则:为每个文件定义 1 个组件。

避免在一个文件中包含多个组件:

angular
  .module('app', ['ngRoute'])
  .controller('SomeController', SomeController)
  .factory('someFactory', someFactory);

function SomeController() { }

function someFactory() { }

Intead,使用一个文件来定义模块:

// app.module.js
angular
  .module('app', ['ngRoute']);

一个文件只使用模块来定义一个组件

// someController.js
angular
  .module('app')
  .controller('SomeController', SomeController);

function SomeController() { }

和另一个文件来定义另一个组件

// someFactory.js
angular
  .module('app')
  .factory('someFactory', someFactory);

function someFactory() { }

当然,对于模块、控制器和服务,还有很多其他规则非常有用,值得一读。

并且感谢 ya_dimon 的注释,上面的代码应该被包裹在 IIFE 中,例如:

(function (window, angular) {
  angular.module('app')
   .controller('Dashboard', function () { });
})(window, window.angular);
于 2015-07-15T08:11:45.060 回答
12

我最近也遇到了这个难题。我和你一样开始使用链式语法,但从长远来看,它在大型项目中变得笨拙。通常我会在单独的文件中创建一个控制器模块、一个服务模块等,并将它们注入到另一个文件中的主应用程序模块中。例如:

// My Controllers File
angular.module('my-controllers',[])
    .controller('oneCtrl',[...])
    .controller('twoCtrl',[...]);

// My Services File
angular.module('my-services',[])
    .factory('oneSrc',[...])
    .facotry('twoSrc',[...]);

// My Directives File
angular.module('my-directives',[])
    .directive('oneDrct',[...])
    .directive('twoDrct',[...]);

// My Main Application File
angular.module('my-app',['my-controllers','my-services','my-directives',...]);

但是随着项目的发展,这些文件中的每一个都变得越来越大。所以我决定根据每个控制器或服务将它们分成单独的文件。我发现在angular.module('mod-name').没有注入数组的情况下使用是你需要的。在一个文件中声明一个全局变量并期望它在另一个文件中随时可用是行不通的,或者可能会产生意想不到的结果。

所以简而言之,我的应用程序看起来像这样:

// Main Controller File
angular.module('my-controllers',[]);

// Controller One File
angular.module('my-controllers').controller('oneCtrl',[...]);

//Controller Two File
angular.module('my-controllers').controller('twoCtrl',[...]);

我也对服务文件进行了此操作,无需更改主应用程序模块文件,您仍将向其中注入相同的模块。

于 2013-11-13T15:47:05.777 回答
8

另一种做法是将控制器、指令等填充到它们自己的模块中,并将这些模块注入您的“主”模块中:

angular.module('app.controllers', [])
  .controller('controller1', ['$scope', function (scope) {
    scope.name = "USER!";
  }]);

angular.module('app.directives', [])
  .directive('myDirective', [function () {
    return {
      restrict: 'A',
      template: '<div>my directive!</div>'
    }
  }]);

angular.module('app', [
  'app.controllers',
  'app.directives'
]);

全局范围内没有任何内容。

http://plnkr.co/edit/EtzzPRyxWT1MkhK7KcLo?p=preview

于 2013-11-13T15:35:25.503 回答
4

我喜欢划分文件和模块。

像这样的东西:

应用程序.js

var myApp = angular.module('myApp', ['myApp.controllers', 'myApp.directives', 'myApp.services']);

myApp.config(['$routeProvider', function($routeProvider) {
    /* routes configs */
    $routeProvider.when(/*...*/);
}]);

指令.js

var myDirectives = angular.module('myApp.directives', []);

myDirectives.directive( /* ... */ );

服务.js

var myServices = angular.module('myApp.services', []);

myServices.factory( /* ... */ );

我不是“链式”的忠实粉丝,所以我更喜欢总是写下我的变量。

于 2013-11-13T15:42:40.560 回答
1

我建议遵循Angularjs 样式指南
他们处理从命名约定到模块化您的应用程序等所有概念。

对于 Angular 2,您可以查看Angular 2 Style Guide

于 2017-09-06T03:03:57.490 回答
0

对我来说,链接是最紧凑的方式:

angular.module("mod1",["mod1.submod1"])

 .value("myValues", {
   ...
 })

 .factory("myFactory", function(myValues){
   ...
 })

 .controller("MainCtrl", function($scope){

   // when using "Ctrl as" syntax
   var MC = this;
   MC.data = ...;
 })
 ;

这样我就可以轻松地在模块之间移动组件,不需要两次声明同一个模块,也不需要任何全局变量。

如果文件太长,解决方案很简单——分成两个文件,每个文件在顶部声明自己的模块。为了提高透明度,我尝试为每个文件保留一个唯一的模块,并将其命名为类似于文件的完整路径。这样我也永远不需要编写没有 的模块[],这是一个常见的痛点。

于 2014-08-11T16:51:12.150 回答