繁体   English   中英

AngularJS 模块声明的最佳实践?

[英]AngularJS best practices for module declaration?

我的应用程序中声明了一堆 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){ ... }]);
    ...
})();

或者,关心是否足够重要? 只是想知道模块声明的“最佳实践”是什么。 提前致谢。

声明模块的“最佳”方式

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

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

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

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

避免使用匿名函数:

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

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

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

我对服务文件也这样做了,无需更改主应用程序模块文件,您仍然会向其中注入相同的模块。

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

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

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

像这样的东西:

应用程序.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( /* ... */ );

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM