[关闭]
@yiranphp 2016-04-06T11:25:49.000000Z 字数 3303 阅读 3144

angularJs模块化

angular


1. setupModuleLoader

publishExternalAPI的阶段设置模块注册器(angular.module),源码比较长,并且使用了多层闭包。
setupModuleLoader源码以及化简版如下

  1. function setupModuleLoader(window) {
  2. var $injectorMinErr = minErr('$injector');
  3. var ngMinErr = minErr('ng');
  4. //该方法很有用,当obj有name属性的时候,作为getter来使用,否则作为setter来使用。
  5. function ensure(obj, name, factory) {
  6. return obj[name] || (obj[name] = factory());
  7. }
  8. var angular = ensure(window, 'angular', Object);
  9. angular.$$minErr = angular.$$minErr || minErr;
  10. // return angular.module = factory();
  11. return ensure(angular, 'module', function() {
  12. var modules = {};
  13. return function module(name, requires, configFn) {
  14. // 后续代码中会使用modules.hasOwnProperty方法,所以不能将模块的名字命名为hasOwnProperty
  15. // angularJs的一个惯用的错误机制:断言,抛出错误,简称断言抛
  16. var assertNotHasOwnProperty = function(name, context) {
  17. if (name === 'hasOwnProperty') {
  18. throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
  19. }
  20. };
  21. assertNotHasOwnProperty(name, 'module');
  22. // 同名模块重新注册
  23. if (requires && modules.hasOwnProperty(name)) {
  24. modules[name] = null;
  25. }
  26. // return modules[name] = factory();
  27. return ensure(modules, name, function() {
  28. if (!requires) {
  29. throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
  30. "the module name or forgot to load it. If registering a module ensure that you " +
  31. "specify the dependencies as the second argument.", name);
  32. }
  33. var invokeQueue = [];
  34. var configBlocks = [];
  35. var runBlocks = [];
  36. var config = invokeLater('$injector', 'invoke', 'push', configBlocks);
  37. var moduleInstance = {
  38. // Private state
  39. _invokeQueue: invokeQueue,
  40. _configBlocks: configBlocks,
  41. _runBlocks: runBlocks,
  42. requires: requires,
  43. name: name,
  44. provider: invokeLater('$provide', 'provider'),
  45. factory: invokeLater('$provide', 'factory'),
  46. service: invokeLater('$provide', 'service'),
  47. value: invokeLater('$provide', 'value'),
  48. constant: invokeLater('$provide', 'constant', 'unshift'),
  49. animation: invokeLater('$animateProvider', 'register'),
  50. filter: invokeLater('$filterProvider', 'register'),
  51. controller: invokeLater('$controllerProvider', 'register'),
  52. directive: invokeLater('$compileProvider', 'directive'),
  53. config: config,
  54. run: function(block) {
  55. runBlocks.push(block);
  56. return this;
  57. }
  58. };
  59. if (configFn) {
  60. config(configFn);
  61. }
  62. return moduleInstance;
  63. // queue默认为invokeQueue,返回的函数的作用就是将[provider, method, arguments]追加到queue数组中
  64. function invokeLater(provider, method, insertMethod, queue) {
  65. if (!queue) queue = invokeQueue;
  66. return function() {
  67. queue[insertMethod || 'push']([provider, method, arguments]);
  68. return moduleInstance;
  69. };
  70. }
  71. });
  72. };
  73. });
  74. }
  75. // 化简版如下
  76. function setupModuleLoader(window) {
  77. // ... ...
  78. return angular.module = (function() {
  79. var modules = {};
  80. return function module(name, requires, configFn) {
  81. return ensure(modules, name, function() {
  82. // ... ...
  83. var moduleInstance = {
  84. // ... ...
  85. };
  86. return moduleInstance;
  87. });
  88. }
  89. })();
  90. }

总结一下:angular.module的使用
1. angular.module(name):getter方式调用,从modules中找注册过的模块,如果未注册过,直接抛出错误
2. angular.module(name, requires):setter方式调用,在modules中注册模块,如果已经注册过同名模块,先清空,后注册
3. angularJs应用中的所有模块都在modules中维护

  1. var module1 = angular.module('mymodule1', []);
  2. var module2 = angular.module('mymodule2', []);
  3. var module3 = angular.module('plunker',['mymodule1', 'mymodule2']);
  4. module3.controller("MainCtrl", ["$scope", function($scope) {
  5. $scope.name = "yiranphp";
  6. console.log('invoke')
  7. }]);
  8. module3.run(["$rootScope", function($rootScope) {
  9. $rootScope.age = 20;
  10. console.log('run');
  11. }])
  12. module3.config(["$httpProvider", function($httpProvider) {
  13. console.log('config');
  14. }]);
  15. console.log(module3);

输出的先后顺序:
moduleInstance,config,run,invoke
可见:通过config、run、controller定义的函数不会立即执行,而是放进了moduleInstance的_invokeQueue、 _configBlocks、runBlocks中,并且是有先后顺序的,后续会详细解释

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注