AngularJS -- Module (模塊)


點擊查看AngularJS系列目錄
轉載請注明出處:http://www.cnblogs.com/leosx/


 

什么是AngularJS的模塊

我們所說的模塊,是你的AngularJS應用程序的一個組成部分,它可以是一個Controller,也可以是一個Service服務,也可以是一個過濾器(Filter),也可以是一個directive(指令)等等…都是屬於一個模塊!

大多數的應用程序都是有一個自己的函數入口方法Main ,用它來進行初始化,以及加載裝配各個模塊,然后這些模塊的組合,構成了你的應用程序,對吧?

但是,but, AngularJS應用程序卻不是這樣的哦,它沒有main 方法,沒有函數入口。代替之的是在模塊中指定聲明這個模塊在AngularJS應用程序中該如何去加載,啟動。這種方法有以下幾個優點:

1) 使用聲明的方式,讓人更加容易理解。

2) 你可以更加容易的讓你的代碼進行重用。

3) 模塊的加載順序就更加容易控制了。因為這些模塊是延遲執行的。

4) 對於進行單元測試就變得更加的方便了。更加可靠,你只需要載入這個模塊就可以進行測試了。

5) 端對端的測試中,你可以使用模塊去重寫配置。

 

還是看看代碼最重要,直接上代碼:

<div ng-app="myApp">
  <div>
    {{ 'World' | greet }}
  </div>
</div>
<script src="https://code.angularjs.org/1.3.0/angular.min.js"></script>
<script type="text/javascript">
  (function(){
    // declare a module
    var myAppModule = angular.module('myApp', []);

    // configure the module.
    // in this example we will create a greeting filter
    myAppModule.filter('greet', function() {
     return function(name) {
        return 'Hello, ' + name + '!';
      };
    });
})();
</script>

單元測試的代碼:

it('should add Hello to the name', function() {
  expect(element(by.binding("'World' | greet")).getText()).toEqual('Hello, World!');
});

效果圖:

module-01

 

有幾個事情需要注意一下的:

1. 關於模塊的API,點擊這里

2. <div ng-app=”myApp”>引用了myApp 模塊。 這既是告訴啟動器,你使用了這個名為myApp的模塊,當AngularJS啟動的時候,它就會去加載力的這個模塊。

3. 在 angular.module(‘myApp’, [] )中,有個空的數組,這個數組是myApp模塊說依賴的模塊的列表.

 

 

推存設置

上面的例子都是非常簡單的。它不是大型應用。我們建議你將你的AngularJS應用程序碎片化,也就是讓你的應用程序變成多個模塊的組合,例如:

1.不同的業務,為一個模塊。

2.一個模塊中,包含很多可以重用的組件(特別是指令和過濾器,以后也可以使用的)

3.一個應用程序級別的模塊,它依賴於上級的模塊,並且它還包含有所有的初始化代碼。。。

在Google上,有一個關於如何編寫大型應用程序的文檔,你可以點擊這里查看。

當然咯!  上面的都是建議,你可以根據你的需求,進行量身定做。比如:

<div ng-app="xmpl">
  <div ng-controller="XmplController">
    {{ greeting }}
  </div>
</div>
<script src="https://code.angularjs.org/1.3.0/angular.min.js"></script>
<script type="text/javascript">
  (function(){
    angular.module('xmpl.service', [])

  .value('greeter', {
    salutation: 'Hello',
    localize: function(localization) {
      this.salutation = localization.salutation;
    },
    greet: function(name) {
      return this.salutation + ' ' + name + '!';
    }
  })

  .value('user', {
    load: function(name) {
      this.name = name;
    }
  });

angular.module('xmpl.directive', []);

angular.module('xmpl.filter', []);

angular.module('xmpl', ['xmpl.service', 'xmpl.directive', 'xmpl.filter'])

  .run(function(greeter, user) {
    // This is effectively part of the main method initialization code
    greeter.localize({
      salutation: 'Bonjour'
    });
    user.load('World');
  })

  .controller('XmplController', function($scope, greeter, user){
    $scope.greeting = greeter.greet(user.name);
  });
})();
</script>

效果圖:

module-02

 

 

模塊的加載和依賴

一個模塊,其實是一個在應用程序的引導程序中運行的,一個配置的集合和運行塊的集合。

1. 配置模塊,它可以在provider提供者中進行注冊,還可以再配置應用階段進行執行。只有provider和常量才能夠被注入到配置塊中去。這樣做是為了防止在配置塊沒有配置完成之前,意外的實例化了服務,這是不被允許的。

2. 運行(run)塊, 是在注入器被創建出來之后和被用於應用程序之后,進行執行的。只有實例對象和常量能夠被注入到 運行(run )塊當中。這樣做的目的是為了防止在應用程序運行期間,增加,修改了系統配置。

來看看例子:

angular.module('myModule', []).
config(function(injectables) { // provider-injector
  // This is an example of config block.
  // You can have as many of these as you want.
  // You can only inject Providers (not instances)
  // into config blocks.
}).
run(function(injectables) { // instance-injector
  // This is an example of a run block.
  // You can have as many of these as you want.
  // You can only inject instances (not Providers)
  // into run blocks
});

 

 

配置塊

其實在模塊上有一些非常方便的方法,它們就相當於是一個 config 配置塊,看例子:

angular.module('myModule', []).
value('a', 123).
factory('a', function() { return 123; }).
directive('directiveName', ...).
filter('filterName', ...);

// is same as

angular.module('myModule', []).
config(function($provide, $compileProvider, $filterProvider) {
  $provide.value('a', 123);
  $provide.factory('a', function() { return 123; });
  $compileProvider.directive('directiveName', ...);
  $filterProvider.register('filterName', ...);
});

當AngularJS在進行引導啟動你的應用程序的時候,它會首先定義所有的常量。然后再在配置塊中使用同一個 常量列表 去注冊它們。

 

 

運行塊(Run)

Run,我們這里叫運行塊,它是最接近Main入口函數的一個方法。運行塊(run) 是建立在AngularJS應用程序之上的。它會在所有的服務配置完畢,注入器被創建完畢之后執行。。 一個運行塊(run block) 通常會包含着單元測試,正因如此,應該把他聲明在一個獨立的模塊(module)當中,這樣,就可以把單元測試給獨立開來了。

 

 

依賴關系

一個模塊,它知道所有它所依賴的其它模塊,也就是說在它加載起來前,需要將它所依賴的其它所有模塊給加載起來。換句換說,對於需要配置塊的模塊來說,配置塊一定是在需要它的模塊初始化之前就被初始化完畢了。 同樣的,運行塊(run block)也是這樣的,一個模塊,會且僅會被加載一次,無論有多少個模塊引用了它,它都只會被加載一次的。

 

 

異步加載(Asynchronous Loading)

Modules are a way of managing $injector configuration, and have nothing to do with loading of scripts into a VM. There are existing projects which deal with script loading, which may be used with Angular. Because modules do nothing at load time they can be loaded into the VM in any order and thus script loaders can take advantage of this property and parallelize the loading process.(這句話實在翻譯不了,英文太爛,有看到並且英文好的哥們兒,望幫忙翻譯下)

 

 

創建和檢索

在使用 angular.module(‘myModule’, [] )的時候得注意,它會創建一個叫做 myModule的模塊,並且會覆蓋掉所有之前叫做 myModule 的模塊。  我們使用 angular.module(‘myModule’) 就可以去查找,檢索我們已經創建的模塊。來個例子:

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

// add some directives and services
myModule.service('myService', ...);
myModule.directive('myDirective', ...);

// overwrites both myService and myDirective by creating a new module
var myModule = angular.module('myModule', []);

// throws an error because myOtherModule has yet to be defined
var myModule = angular.module('myOtherModule');

 

 

單元測試

單元測試是一個很好的去初始化你的應用模塊,並且調用它的一個小的應用。  有結構的模塊對於單元測試時非常有用的,可以很好的找到關注重點。

一個模塊只能在注入器(injector) 中被加載一次,且僅有一次。通常,一個Angular 應用程序只有一個 注入器(injector) 而且所有模塊只會被加載一次。但是每個單元測試都會有自己的注入器(injector) ,而且模塊可以被加載多次。 在我們的所有例子中,都遵循了模塊定義的這個規則:

angular.module('greetMod', []).

factory('alert', function($window) {
  return function(text) {
    $window.alert(text);
  }
}).

value('salutation', 'Hello').

factory('greet', function(alert, salutation) {
  return function(name) {
    alert(salutation + ' ' + name + '!');
  }
});

 

我們來寫一些單元測試,來看看在單元測試當中如何重寫配置

describe('myApp', function() {
// load application module (`greetMod`) then load a special
// test module which overrides `$window` with a mock version,
// so that calling `window.alert()` will not block the test
// runner with a real alert box.
beforeEach(module('greetMod', function($provide) {
  $provide.value('$window', {
    alert: jasmine.createSpy('alert')
  });
}));

// inject() will create the injector and inject the `greet` and
// `$window` into the tests.
it('should alert on $window', inject(function(greet, $window) {
  greet('World');
  expect($window.alert).toHaveBeenCalledWith('Hello World!');
}));

// this is another way of overriding configuration in the
// tests using inline `module` and `inject` methods.
it('should alert using the alert service', function() {
  var alertSpy = jasmine.createSpy('alert');
  module(function($provide) {
    $provide.value('alert', alertSpy);
  });
  inject(function(greet) {
    greet('World');
    expect(alertSpy).toHaveBeenCalledWith('Hello World!');
  });
});
});


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM