AngularJS best practices for module declaration?

I have a bunch of Angular modules declared in my app. I originally started declaring them using the "chained" syntax like this:

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

But I decided that wasn't very easy to read, so I started declaring them using a module variable like this:

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


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


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

The second syntax seems a lot more readable to me, but my only complaint is that this syntax leaves the mod variable out in the global scope. If I ever have some other variable named mod, it would be overridden with this next one (and other issues associated with global variables).

So my question is, is this the best way? Or would it be better to do something like this?:

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

Or does it even matter enough to care? Just curious to know what the "best practices" are for module declaration. Thanks in advance.

87721 次浏览

声明模块的“最佳”方法

由于角度是在全局范围本身和模块保存到其变量,您可以通过 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. 可以使用“使用严格”的函数形式;
  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'
]);

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

EDIT: 只是因为它是相关的,而且我最近又碰到了这个问题: 注意只创建一次模块(通过向 angular.module-function 添加第二个参数)。这将使您的应用程序混乱,并且非常难以检测。

2015年分类模块编辑: One and a half year of angular-experience later, I can add that the benefits from using differently named modules within your app are somewhat limited as AMD still does not really work well with Angular and services, directives and filters are globally available inside the angular context anyway (as exemplified here). There is still a semantic and structural benefit though and it might be helpful being able to include/ exclude a module with a single line of code commented in or out.

它也几乎是 按类型分隔子模块从来没有多大意义(例如“ myMapSubModule.controller”) ,因为它们通常相互依赖。

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

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

我喜欢划分我的文件和模块。

就像这样:

应用程序

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( /* ... */ );

Service.js

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


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

我不太喜欢“链式风格”,所以我总是喜欢写下我的变量。

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

// 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',[...]);

I did this to the services file as well, no need to change the main application module file you'd still be injecting the same modules into that.

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

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 = ...;
})
;

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

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

我喜欢 Johnpapa 的 角形导轨角形导轨,这里有一些与这个问题相关的规则:

规则: 命名与匿名函数

避免使用匿名函数:

// 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, use one file to define the module:

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

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

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


function SomeController() { }

and another file to define another component

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


function someFactory() { }

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

And thanks to comment of ya_dimon, the above code should be wrapped in IIFE, for example:

(function (window, angular) {
angular.module('app')
.controller('Dashboard', function () { });
})(window, window.angular);

我建议跟随 Angularjs 风格指南
They handle all concept from naming convention, to modularize your app and so on.

对于角度2,你可以检查 角度2风格指南