AngularJS中的Module类负责定义应用如何启动,它还可以通过声明的方式定义应用中的各个片段。我们来看看它是如何实现这些功能的。

一.Main方法在哪里

如果你是从Java或者Python编程语言转过来的,那么你可能很想知道AngularJS里面的main方法在哪里?这个把所有东西启动起来,并且第一个被执行的方法在哪里?JavaScript代码里面负责实例化并且把所有东西组合到一起,然后命令应用开始运行的那个方法在哪里?

事实上,AngularJS并没有main方法,AngularJS使用模块的概念来代替main方法。模块允许我们通过声明的方式来描述应用中的依赖关系,以及如何进行组装和启动。使用这种方式的原因如下:

1.模块是声明式的。这就意味着它编写起来更加容易,同时理解起来也很容易,阅读它就像读普通的英文一样!

2.它是模块化的。这就迫使你去思考如何定义你的组件和依赖关系,让它们变得更加清晰。

3.它让测试更加容易。在单元测试吕,你可以有选择地加入模块,并且可以避免代码中存在无法进行单元测试的内容。同时,在场景测试中,你可以加载其他额外的模块,这样就可以更好地和其他组件配合使用。

例如,在我们的应用中有一个叫做"MyAwesomeApp"的模块。在HTML里面,只要把以下内容添加到<html>标签中(或者从技术上说,可以添加到任何标签中):

  1. <html ng-app="MyAwesomeApp">

ng-app指令就会告诉AngularJS使用MyAwesomeApp模块来启动你的应用。那么,应该如何定义模块呢?举例来说,我们建议你为服务、指令和过滤器分别定义不同的模块。然后你的主模块可以声明依赖这些模块。

这样可以使得模块管理更加容易,因为它们都是良好的、完备的代码块,每个模块有且只有一种职能。同时,单元测试可以只加载它们所关注的模块,这样就可以减少初始化的次数,单元测试也会变得更精致、更专注。

二.加载和依赖

模块加载动作发生在两个不同的阶段,这一点从函数名上面就可以反映出来,它们分别是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(打招呼)函数的实例,这个函数需要一条问候语来初始化:

  1. function Greeter(salutation) {
  2. this.greet = function(name) {
  3. return salutation + ' ' + name;
  4. };
  5. }

greeter函数示例如下:

  1. myApp.factory('greeter', function(salut) {
  2. return new Greeter(salut);
  3. });

然后可以这样来调用它:

  1. var myGreeter = greeter('Halo');

9.service(name,object)

factory和service之间的不同点在于,factory会直接调用传递给它的函数,然后返回执行的结果;而service将会使用"new"关键字来调用传递给它的构造方法,然后再返回结果。所以,前面的greeter Factory可以替换成下面这个greeter Service:

  1. myApp.service('greeter', Greeter);

每当我们需要一个greeter实例的时候,AngularJS就会调用新的Greeter()来返回一个实例。

10.provider(name,providerFn)

provider是这几个方法中最复杂的部分(显然,也是可配置性最好的部分)。provider中既绑定了factory也绑定了service,并且在注入系统准备完毕之前,还可以享受到配置provider函数的好处(也就是config块)。

我们来看看使用provider改造之后的greeter Service是什么样子:

  1. myApp.provider('greeter', function() {
  2. var salutation = 'Hello';
  3. this.setSalutation = function(s) {
  4. salutation = s;
  5. }
  6. function Greeter(a) {
  7. this.greet = function() {
  8. return salutation + ' ' + a;
  9. }
  10. }
  11. this.$get = function(a) {
  12. return new Greeter(a);
  13. };
  14. });

这样我们就可以在运行时动态设置问候语了(例如,可以根据用户使用的不同语言进行设置)。

  1. var myApp = angular.module(myApp, []).config(function(greeterProvider) {
  2. greeterProvider.setSalutation('Namaste');
  3. });

每当有人需要一个greeter实例时,AngularJS就会在内部调用$get方法。

附:angular.module('MyApp',[...])和angular.module('MyApp')之间有一个很小但是却很重要的不同点

angular.module('MyApp',[...])会创建一个新的Angular模块,然后把方括号([...])中的依赖列表加载进来;而angular.module('MyApp')会使用由第一个调用定义的现有的模块。

所以,对于以下代码,你需要保证在整个应用中只会使用一次:

  1. angular.module('MyApp', [...])   //如果你的应用是模块化的,这里可能是MyModule

如果你不打算把模块的引用存到一个变量中,然后在整个应用中通过这个变量来引用模块,那么,在其他文件中使用angular.module(MyApp)的方式可以保证得到正确的AngularJS模块引用。模块上的所有东西都必须通过访问这个模块引用来定义,或者在模块定义的地方把那些必备的内容添加上去。

文章转自:http://bijian1013.iteye.com/blog/2111306

AngularJS Moudle 函数讲解的更多相关文章

  1. avascript中的this与函数讲解

    徐某某 一个半路出家的野生程序员 javascript中的this与函数讲解 前言 javascript中没有块级作用域(es6以前),javascript中作用域分为函数作用域和全局作用域.并且,大 ...

  2. Python中高阶函数讲解

    高阶函数讲解 1. 常规高阶函数 递归函数 格式:def func_name(variable): '''__doc__'''#函数的说明文档 if 条件表达式:#限制递归退出值 pass retur ...

  3. python ---split()函数讲解

    python ---split()函数讲解 split中文翻译为分裂. 在python用于分割字符串使用. split()就是将一个字符串分裂成多个字符串组成的列表. split()可以传入参数,也可 ...

  4. MySql UNIX_TIMESTAMP和FROM_UNIXTIME函数讲解

    MySql UNIX_TIMESTAMP和FROM_UNIXTIME函数讲解 by:授客 QQ:1033553122 1. unix_timestamp(date)将时间转换为时间戳,如果参数为空,则 ...

  5. Spark Streaming中的操作函数讲解

    Spark Streaming中的操作函数讲解 根据根据Spark官方文档中的描述,在Spark Streaming应用中,一个DStream对象可以调用多种操作,主要分为以下几类 Transform ...

  6. linux xfs文件系统无法用readdir获取dirent文件类型d_type则用stat获取暨stat函数讲解

    stat函数讲解 表头文件:    #include <sys/stat.h>             #include <unistd.h>定义函数:    int stat ...

  7. linux stat函数讲解 -(转自秋水Leo)

    stat函数讲解表头文件:    #include <sys/stat.h>             #include <unistd.h>定义函数:    int stat( ...

  8. Spark常用函数讲解之Action操作

    摘要: RDD:弹性分布式数据集,是一种特殊集合 ‚ 支持多种来源 ‚ 有容错机制 ‚ 可以被缓存 ‚ 支持并行操作,一个RDD代表一个分区里的数据集RDD有两种操作算子:         Trans ...

  9. Spark常用函数讲解之键值RDD转换

    摘要: RDD:弹性分布式数据集,是一种特殊集合 ‚ 支持多种来源 ‚ 有容错机制 ‚ 可以被缓存 ‚ 支持并行操作,一个RDD代表一个分区里的数据集RDD有两种操作算子:         Trans ...

随机推荐

  1. MySQL Cluster 数据分布(分区、分组)

    数据分布 1.MySQL Cluster自动分区数据表(也可能使用用户自定义分区),将数据分布到分区中: 2.一个数据表被划分到多个Data Node分区中,数据在分区中被”striped”: 3.主 ...

  2. position:fixed失效

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. Hibernate参数一览表

    参考文章地址:http://www.blogjava.net/i369/articles/194855.html Hibernate 参数设置一览表 属性名 用途 hibernate.dialect ...

  4. Android 一些基本组件的使用

    Dialog 基本用法 ,带自定义view AlertDialog dialog = new AlertDialog.Builder(context).setTitle("写入信息" ...

  5. C++中的 :: 用法

    ::是运算符中等级最高的,它分为三种:1)global scope(全局作用域符),用法(::name)2)class scope(类作用域符),用法(class::name)3)namespace ...

  6. ffmpeg-20160908[09,10,13,15,19,21,22,24]-bin.7z

    ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 5 屏幕横向放大 20 像素 6 屏幕横向缩小 20 像素 S 下一帧 [ -2秒 ] +2 ...

  7. LINK1123:failure during conversion to COFF:file invalid or corrupt

    参考 http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=20726500&id=4528320 试了微软官方说明:http ...

  8. 解决NSData转NSString返回nil的问题

    // 字符串转Data NSString *str =@"jesfds"; NSData *data =[str dataUsingEncoding:NSUTF8StringEnc ...

  9. IIS7.5 平台.NET无后缀名伪静态实现办法-服务器配置

    搞了好久才弄好,记下来防止忘记: 1)首先新建一个应用程序池,名称任意,比如:nettest,托管管道模式先暂时设置为集成模式,等下面的一系列设置完成之后再设置成经典模式:2)部署好站点,并将此站点的 ...

  10. 为 placeholder 自定义样式

    textarea::-webkit-input-placeholder{ padding: 1em; } textarea::-moz-placeholder{ padding: 1em; } 同理, ...