AngularJS中的Module类负责定义应用如何启动,它还能够经过声明的方式定义应用中的各个片断。咱们来看看它是如何实现这些功能的。html
一.Main方法在哪里编程
若是你是从Java或者Python编程语言转过来的,那么你可能很想知道AngularJS里面的main方法在哪里?这个把全部东西启动起来,而且第一个被执行的方法在哪里?JavaScript代码里面负责实例化而且把全部东西组合到一块儿,而后命令应用开始运行的那个方法在哪里?app
事实上,AngularJS并无main方法,AngularJS使用模块的概念来代替main方法。模块容许咱们经过声明的方式来描述应用中的依赖关系,以及如何进行组装和启动。使用这种方式的缘由以下:编程语言
1.模块是声明式的。这就意味着它编写起来更加容易,同时理解起来也很容易,阅读它就像读普通的英文同样!ide
2.它是模块化的。这就迫使你去思考如何定义你的组件和依赖关系,让它们变得更加清晰。模块化
3.它让测试更加容易。在单元测试吕,你能够有选择地加入模块,而且能够避免代码中存在没法进行单元测试的内容。同时,在场景测试中,你能够加载其余额外的模块,这样就能够更好地和其余组件配合使用。函数
例如,在咱们的应用中有一个叫作"MyAwesomeApp"的模块。在HTML里面,只要把如下内容添加到<html>标签中(或者从技术上说,能够添加到任何标签中):单元测试
<html ng-app="MyAwesomeApp">
ng-app指令就会告诉AngularJS使用MyAwesomeApp模块来启动你的应用。那么,应该如何定义模块呢?举例来讲,咱们建议你为服务、指令和过滤器分别定义不一样的模块。而后你的主模块能够声明依赖这些模块。测试
这样可使得模块管理更加容易,由于它们都是良好的、完备的代码块,每一个模块有且只有一种职能。同时,单元测试能够只加载它们所关注的模块,这样就能够减小初始化的次数,单元测试也会变得更精致、更专一。this
二.加载和依赖
模块加载动做发生在两个不一样的阶段,这一点从函数名上面就能够反映出来,它们分别是Config代码块和Run代码块(或者叫作阶段)。
1.Config代码块
在这一阶段里面,AngularJS会链接并注册好全部数据源。所以,只有数据源和常量能够注入到Config代码块中。那些不肯定是否已经初始化好的服务不能注入进来。
2.Run代码块
Run代码块用来启动你的应用,而且在注射器建立完成以后开始执行。为了不在这一点开始以后再对系统进行配置操做,只有实例和常量能够被注入到Run代码块中。你会发现,在AngularJS中,Run代码块是与main方法最相似的东西。
三.快捷方法
利用模块能够作什么呢?咱们能够用它来实例化控制器、指令、过滤器以及服务,可是利用模块类还能够作更多事情。以下模块配置的API方法:
1.config(configFn)
利用此方法能够作一些注册工做,这些工做须要在模块加载时完成。
2.constant(name, object)
此方法会首先运行,因此你能够用它来声明整个应用范围内的常量,而且让它们在全部配置(config方法)和实例(后面的全部方法,例如controller、service等)方法中可用。
3.controller(name,constructor)
它的基本做用是配置好控制器方便后面使用。
4.directive(name,directiveFactory)
可使用此方法在应用中建立指令。
5.filter(name,filterFactory)
容许你建立命名的AngularJS过滤器,就像前面章节所讨论的那样。
6.run(initializationFn)
若是你想要在注射器启动以后执行某些操做,而这些操做须要在页面对用户可用以前执行,就可使用此方法。
7.value(name,object)
容许在整个应用中注射值。
8.factory(name,factoryFn)
若是你有一个类或者对象,须要首先为它提供一些逻辑或者参数,而后才能对它初始化,那么你就可使用这里的factory接口。factory是一个函数,它负责建立一些特定的值(或者对象)。咱们来看一个greeter(打招呼)函数的实例,这个函数须要一条问候语来初始化:
function Greeter(salutation) { this.greet = function(name) { return salutation + ' ' + name; }; }
greeter函数示例以下:
myApp.factory('greeter', function(salut) { return new Greeter(salut); });
而后能够这样来调用它:
var myGreeter = greeter('Halo');
9.service(name,object)
factory和service之间的不一样点在于,factory会直接调用传递给它的函数,而后返回执行的结果;而service将会使用"new"关键字来调用传递给它的构造方法,而后再返回结果。因此,前面的greeter Factory能够替换成下面这个greeter Service:
myApp.service('greeter', Greeter);
每当咱们须要一个greeter实例的时候,AngularJS就会调用新的Greeter()来返回一个实例。
10.provider(name,providerFn)
provider是这几个方法中最复杂的部分(显然,也是可配置性最好的部分)。provider中既绑定了factory也绑定了service,而且在注入系统准备完毕以前,还能够享受到配置provider函数的好处(也就是config块)。
咱们来看看使用provider改造以后的greeter Service是什么样子:
myApp.provider('greeter', function() { var salutation = 'Hello'; this.setSalutation = function(s) { salutation = s; } function Greeter(a) { this.greet = function() { return salutation + ' ' + a; } } this.$get = function(a) { return new Greeter(a); }; });
这样咱们就能够在运行时动态设置问候语了(例如,能够根据用户使用的不一样语言进行设置)。
var myApp = angular.module(myApp, []).config(function(greeterProvider) { greeterProvider.setSalutation('Namaste'); });
每当有人须要一个greeter实例时,AngularJS就会在内部调用$get方法。
附:angular.module('MyApp',[...])和angular.module('MyApp')之间有一个很小可是却很重要的不一样点
angular.module('MyApp',[...])会建立一个新的Angular模块,而后把方括号([...])中的依赖列表加载进来;而angular.module('MyApp')会使用由第一个调用定义的现有的模块。
因此,对于如下代码,你须要保证在整个应用中只会使用一次:
angular.module('MyApp', [...]) //若是你的应用是模块化的,这里多是MyModule
若是你不打算把模块的引用存到一个变量中,而后在整个应用中经过这个变量来引用模块,那么,在其余文件中使用angular.module(MyApp)的方式能够保证获得正确的AngularJS模块引用。模块上的全部东西都必须经过访问这个模块引用来定义,或者在模块定义的地方把那些必备的内容添加上去。