AngularJS中的模块和依赖注入

    AngularJS最需要重点了解的方面是依赖注入和它与模块联系的方法。依赖是许多服务器端语言的共同概念,但在JavaScript中,直到AngularJS出现后,它才真正得到广泛实现。

    依赖注入允许AngularJS模块保持一个非常整洁,有组织的形式,并更容易访问其他模块的功能,当被正确地实现时,它也往往会减少相当数量的代码。

    本篇文章提供了依赖注入的基本概况,然后介绍如何创建提供功能的模块,以及如何在其他模块与其它AngularJS组件(如控制器)中使用这个功能。

1,模块和依赖注入概述

    下面将介绍AngularJS模块和依赖注入背后的概念。了解模块是如何利用依赖注入来访问其他模块的功能将事你更容易在AngularJS框架中实现你的代码。

1.1,了解模块

    AngularJS模块是一种容器,它让你把代码隔离并组织成简洁,整洁,可重复使用的块。模块本身不提供直接的功能,但它们包含其他提供功能的对象的实例,如控制器,过滤器,服务,动画等。

    你可以通过定义其提供的对象来构建模块。然后通过依赖注入将模块连接在一起,构建一个完整的应用程序。

    AngularJS建立在模块原理上。大部分由AngularJS提供的功能都内置到一个名为ng的模块中。

1.2,依赖注入

    完全掌握依赖注入的概念可能是困难的。然而,一旦你理解它的基础知识,AngularJS实现就变得很清楚了。依赖注入是在许多服务器端语言中众所周知的设计模式,但在此之前,它在JavaScript中一直没有得到广泛应用。

扫描二维码关注公众号,回复: 1375760 查看本文章

    AngularJS依赖注入的思想是定义依赖对象并动态地把它注入另一个对象,使得所有的依赖对象所提供的功能都可用。AngularJS通过利用提供器和注入器服务提供依赖注入。

    提供器本质上是关于如何创建一个具有必要功能的对象实例的定义。提供器应该被定义为AngularJS模块的一部分。一个模块把提供器注册到注入器的服务器中。在AngularJS应用程序中,一个提供器对象只创建一个实例。

    注入器服务负责跟踪提供器对象的实例。对于每个注册了提供器的模块。都会创建一个注入器服务实例。当对一个提供器对象发出一个依赖的请求时,注入器服务首先检查是否该实例已经存在于注入器缓存。如果是这样的,则该实例被使用。如果在缓存中没有找到该实例,则使用提供器的定义创建一个新的实例,把它存储在缓存中,然后再将其返回。

2,定义AngularJS模块

    现在你明白了模块和依赖注入的关系,你还需要观察实现AngularJS模块的过程。AngularJS模块被实现为两个阶段:配置阶段和运行阶段。以下各节讨论这些阶段和把提供器添加到AngularJS模块的基本过程。

2.1,创建AngularJSModule对象

    创建AngularJS模块是一个简单的过程,涉及调用angular.module()方法。此方法创建一个Module对象的实例,把它注册到注入器服务,然后返回新建的Module对象的实例,你可以用它来实现提供器的功能。angular.module()方法使用以下语法:

angular.module(name,[requires],[configFn])

    name参数是该模块被注册在注入器服务中的名称。requires参数是要被添加到注入器服务的供这个模块使用的模块名的数组。如果需要另外一个模块的功能,你需要将它添加到require列表。默认情况下,ng模块会自动被添加到每个实例化模块,让你无须在列表中明确指定ng就可以访问AngularJS提供器

    所有依赖的实例都被自动注入到一个模块的实例中。依赖可以是模块,服务,以及在注入器服务中注册的任何其他对象。configFn参数是在模块配置阶段调用的另一个函数。配置函数将在下一节中介绍。

    以下是创建一个依赖$window和$http服务的AngularJS模块的例子。该定义还包括一个配置函数,它增加了一个名为myvalue的值提供器:

var myModule = angular.module('myModule',['$window','$http'],function(){
	$provide.value('myValue','Some Value');
});

    如果你不指定requires参数,那么不会创建一个Module对象,而是返回已经创建的实例。例如,下面的代码覆盖上面的实例定义:

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

    但是,下面的代码返回上面创建的实例,因为在参数列表的require数组中没有列出依赖:

var myModule3 = angular.module('myModule');

2.2,使用配置块

    当一个模块被定义时,执行AngularJS模块配置阶段。在此阶段中,任何提供器都被注入到依赖注入器。你应该仅把配置和提供器代码放入配置块中。

    你可以通过在Module对象的实例上使用以下语法调用config()方法实现配置块:

config(function([injectable,...]))

    一个带有injectable参数的函数被传入。injectable参数的典型值为提供器服务函数,如$provide。

    下面是一个基本配置块的例子:

var myModule = angular.module('myModule',[]).
	config(function($provide,$filterProvider){
		$provide.value("startTime",new Date());
		$filterProvider.register('myFilter',function(){});
	});

    请注意,$provide和$filterProvider服务被传递到config函数。它们用来把命名为startTime的值提供器和命名为myFilter的过滤器提供器注册到注入器服务。

2.3,使用运行块

    一旦整个配置块完成,就可以执行一个AngularJS模块的运行阶段了。在这个阶段,你可以实现实例化模块所需的任何代码。在运行块中,不能实现任何提供器代码。因为在这个时刻,整个模块应该已经配置完成并且已注册到依赖注入器了。

    run块是使用下面的语法通过调用Module对象的run()方法实现的:

run(function([injectable,...]))

    带有实例injectable参数的函数被传入,injectable参数只应该是注入器的实例,因为配置应该已经完成。

    以下是从上面的例子继续运行块的基本实现:

myModule.run(function(startTime){
	startTime.setTime((new Date()).getTime());
});

    请注意,在上面config()节所定义的startTime实例被传递到run()函数。这允许run()函数来把startTime提供器更新为一个新值。

2.4,把提供器更新到AngularJS模块

    Module对象提供了几个辅助方法,用于将提供器作为config()方法的替代来使用。这些方法更易于使用并使你的代码更清晰。你可以把两种类型的提供器对象添加到AngularJS模块。所有这些方法都接受两个参数:将注册到依赖注入器的名称和定义了如何构建特定对象的提供器函数。以下各节更详细地描述了这些方法。

    专门的AngularJS对象提供器

    Module对象提供特殊的构造方法来为你需要在模板中实现的AngularJS对象添加提供器。这些专门的方法允许你添加一下几种类型对象的定义:

  • animation(name,animationFactory)
  • controller(name,controllerFactory)
  • filter(name,filterFactory)
  • directive(name,directiveFactory)

    使用这些特定方法的原因是,对这些提供器方法,在AngularJS中有相应的animation,controller,filter和directive对象定义。

    如下是一个基本控制器定义:

var mod = angular.module('myMod',[]);
mod.controller('myController',function($scope){
	$scope.someValue = 'Some Value';
});

    这段代码创建了一个名为mod的简单模块,然后调用controller()方法,并传入myController和controllerFactory函数。该controllerFactory函数接受$scope变量作为参数。这是因为AngularJS具有内置控制器对象并知道所有控制器对象都必须接收一个作用域对象作为第一个参数。

    服务提供器

    服务提供器是一类独特的提供器,因为所得到的提供器对象不存在已有的特定格式。相反,提供器作为一个服务来提供功能。AngularJS为构建服务提供一些具体的创建方法,并通过以下方法公开它们。

  • value(name,object):这是所有提供器中最基础的。object参数被简单地分配到name,所以在注入器中name值和object值之间有直接的关系。
  • constant(name,object):这与value()方法类似,但value是不可更改的,此外,在应用其他的提供器方法之前,constant()方法先被应用
  • factory(name,factoryFunction):此方法使用factoryFunction参数来构建一个将通过注入器来提供的对象。
  • service(name,serviceFactory):此方法添加了更加面向对象的方法来实现提供器对象的概念。许多AngularJS内置功能都是通过服务提供器提供的。
  • provider(name,providerFartory):此方法是所有其他方法的核心。虽然它提供大多数功能,但因为其他功能都更简单,所以它不被频繁地使用。

    下面是一个简单的代码清单:

var mod = angular.module('myMod',[]);
mod.constant("cID","ABC");
mod.value("counter",0);
mod.value("image",{name:'box.jpg',height:12,width:20});

    这段代码创建了一个名为mod的简单模块,然后定义了constant()和两个value()提供器。在这些方法中定义的值被注册在myMod模块的注入器服务器中,并随后通过名字访问。

3,实现依赖注入

    一旦你定义了一个模块和相应的提供器,就可以把该模块作为其他模块,控制器和其他各种AngularJS对象的依赖来添加。需要设置依赖于提供器的对象的$inject属性值。该$inject属性包含应注入到它的提供器名称的数组。

    例如,下面的代码定义了接受$scope和appMsg参数的基本控制器。然后将$inject属性设置为包含$scope的数组,这是提供对作用域和一个自定义appMsg访问的AngularJS作用域服务。$scope和appMsg都被注入到myController函数中:

var myController = function($scope,appMsg){
	$scope.message = appMsg;
};
controller['$inject'] = ['$scope','appMsg'];
myApp.myController('controllerA',controller);

    当你实现特定的对象时,这种方法可能变得有点笨拙,所以AngularJS还提供了更优雅一点的方法来注入依赖,它使用下面的语法来代替正常的构造函数:

[providerA,providerB,...,function(objectA,objectB,...){}]

    例如,上面的代码也可以被改写为:

myApp.myController('controllerA',['$scope','appMsg',function($scope,appMsg){
	$scope.message = appMsg;
}]);

    下面的代码清单显示了如何实现有两个模块的依赖注入,每个模块都有一个值提供器和一个控制器。

var myMod = angular.module('myMod',[]);
myMod.value('modMsg','Hello from My Module');
myMod.controller('controllerB',['$scope','modMsg',function($scope,msg){
	$scope.message = msg;
}]);
var myApp = angular.module('myApp',[myMod]);
myApp.value('appMsg','Hello from My App');
myApp.controller('controllerA',['$scope','appMsg',function($scope,msg){
	$scope.message = msg;
}]);
<!doctype html>
<html ng-app="myApp">
<head>
	<title>AngularJS Dependency Injection</title>
</head>
<body>
	<div ng-controller="controllerA">
		<h2>Application Message:</h2>
		{{message}}
	</div><hr>
	<div ng-controller="controllerB">
		<h2>Module Message:</h2>
		{{message}}
	</div>
	<script src="js/angular.js"></script>
	<script src="js/injector.js"></script>
</body>
</html>


猜你喜欢

转载自blog.csdn.net/qq_39263663/article/details/80514730