AngularJS开发指南10:AngularJS依赖注入的详解
依赖注入是一种软件设计模式,用来处理代码的依赖关系。
一般来说有三种方法让函数获得它需要的依赖:
它的依赖是能被创建的,一般用new操作符就行。
能够通过全局变量查找依赖。
依赖能在需要时被导入。
前两种方式都不是很好,因为它们需要对依赖硬编码,使得修改依赖的时候变得困难。特别是在测试的时候不好办,因为对某个部分进行孤立的测试常常需要模拟它的依赖。
第三种方式是最好的,因为它不必在组件中去主动寻找和获取依赖,而是由外界将依赖传入。
举个例子:
function SomeClass(greeter) {
this.greeter = greeter
}
SomeClass.prototype.doSomething = function(name) {
this.greeter.greet(name);
}
上面的例子中SomeClass不关心去哪里获得叫greeter的依赖。这是我们想要的结果,但是这也同时把获取依赖的任务交给了负责创建SomeClass的代码。
每一个AngularJS应用都有一个注入器(injector)用来处理依赖的创建。注入器是一个负责查找和创建依赖的服务定位器。举个例子:
angular.module('myModule', []).
// 告诉注入器如何来创建这个greeter
// 注意这个greeter本身依赖'$window'
factory('greeter', function($window) {
// 这个方法,我们叫做工厂方法,它的作用是用来创建这个greeter服务
return {
greet: function(text) {
$window.alert(text);
}
};
})
// 在模块myModule中,创建一个新的注入器
// (这经常在angular启动时自动完成)
var injector = angular.injector('myModule');
// 从这个注入器中得到greeter这个服务
var greeter = injector.get('greeter');
通过请求依赖的方式解决了硬编码的问题,但是同样也意味着注入器需要在应用中传递,这违反了迪米特法则。我们通过使用下面这个例子中声明的方式来将依赖查找都给注入器来解决。
<!-- Given this HTML -->
<div ng-controller="MyController">
<button ng-click="sayHello()">Hello</button>
</div>
// And this controller definition
function MyController($scope, greeter) {
$scope.sayHello = function() {
greeter('Hello World');
};
}
//'ng-controller'指令做了以下事情
injector.instantiate(MyController);
注意,通过使用ng-controller来实例化控制器类,是的,控制器和注入器不再相关联,这是最好的结果。控制器中的代码可以简单的请求依赖而不必处理注入器。这种方式就没有破坏迪米特法则。
注入器怎么知道需要注入什么依赖呢?
注入器需要应用提供一些标记来表示自己需要的依赖。在关于AngularJS的某些API文档中你会看到函数都是被注入器调用的。注入器需要知道函数需要什么依赖。下面有三个等效的表示自己需要的依赖的方法。这些方法可以互相替换,并且是等效的。
(1)最简单的处理依赖的方法,就是假设函数的参数名就是依赖的名字
function MyController($scope, greeter) {
...
}
给出一个注入器,可以通过检查函数声明来获取函数名,从而知道需要依赖的函数。在上面的例子中,$scope和greeter是需要注入到函数中的依赖。
坦白的来讲,用了这种方法就不能使用JavaScript minifiers/obfuscators(一些用来缩短JS的类库)了,因为它们会改变变量名。
(2)要允许压缩类库重命名函数的参数,同时注入器又能正确处理依赖的话,函数需要使用$inject属性。这个属性是一个包含依赖的名称的数组。
var MyController = function(renamed$scope, renamedGreeter) {
...
}
MyController.$inject = ['$scope', 'greeter'];
注意$inject标记里的值和函数声明的参数是对应的。
这种方式适合用于控制器的声明,因为控制器有了明确的声明标记。
(3)有时候用$inject标记不是很方便,比如用来声明指令的时候。
使用$inject会导致代码膨胀:
var greeterFactory = function(renamed$window) {
...;
};
greeterFactory.$inject = ['$window'];
someModule.factory('greeter', greeterFactory);
这种情况我们就推荐使用第三种方式:
someModule.factory('greeter', ['$window', function(renamed$window) {
...;
}]);
依赖注入在AngularJS中很普遍,一般用在控制器和工厂方法中。
控制器中的依赖注入:
控制器是负责应用行为的类。推荐的控制器声明方法如下:
var MyController = function(dep1, dep2) {
...
}
MyController.$inject = ['dep1', 'dep2'];
MyController.prototype.aMethod = function() {
...
}
工厂方法的依赖注入:
工厂方法负责创建AngularJS中的大部分对象。比如指令,服务,过滤器。工厂方法一般在模块中使用,推荐的方法如下:
angular.module('myModule', []).
config(['depProvider', function(depProvider){
...
}]).
factory('serviceId', ['depService', function(depService) {
...
}]).
directive('directiveName', ['depService', function(depService) {
...
}]).
filter('filterName', ['depService', function(depService) {
...
}]).
run(['depService', function(depService) {
...
}]);
加油!
AngularJS开发指南10:AngularJS依赖注入的详解的更多相关文章
- AngularJS开发指南14:依赖注入
推荐两种使用场景: 1.控制器中的依赖注入 控制器是负责应用行为的类.推荐的控制器声明方法如下: var MyController = function(dep1, dep2) { ... } MyC ...
- Spring 依赖注入方式详解
平常的Java开发中,程序员在某个类中需要依赖其它类的方法. 通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. Spring提出了依赖注入的思想,即依赖类不由 ...
- Spring 依赖注入方式详解(四)
IoC 简介 平常的Java开发中,程序员在某个类中需要依赖其它类的方法. 通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. Spring提出了依赖注入的思想 ...
- Unity依赖注入使用详解
写在前面 构造器注入 Dependency属性注入 InjectionMethod方法注入 非泛型注入 标识键 ContainerControlledLifetimeManager单例 Unity注册 ...
- SpringDI四种依赖注入方式详解
文章已托管到GitHub,大家可以去GitHub查看阅读,欢迎老板们前来Star!搜索关注微信公众号 [码出Offer] 领取各种学习资料! LOGO SpringDI(依赖注入) 一.DI概述 De ...
- .NET Core 中依赖注入框架详解 Autofac
本文将通过演示一个Console应用程序和一个ASP.NET Core Web应用程序来说明依赖注入框架Autofac是如何使用的 Autofac相比.NET Core原生的注入方式提供了强大的功能, ...
- 依赖注入(IOC) 详解
https://blog.csdn.net/qq_27093465/article/details/52547290 https://blog.csdn.net/qq_27093465/article ...
- 【转】angularjs指令中的compile与link函数详解
这篇文章主要介绍了angularjs指令中的compile与link函数详解,本文同时诉大家complie,pre-link,post-link的用法与区别等内容,需要的朋友可以参考下 通常大家在 ...
- angularjs指令中的compile与link函数详解
这篇文章主要介绍了angularjs指令中的compile与link函数详解,本文同时诉大家complie,pre-link,post-link的用法与区别等内容,需要的朋友可以参考下 通常大家在 ...
随机推荐
- Uva-11374-Airport Express
A - Airport Express Time Limit:1000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Appoi ...
- js控制iframe跳转
网页:<iframe src="" id="iframe_a" name="iframe_a" style="width:1 ...
- Dictionary(HashMap)的实现
什么是哈希表? 哈希表(Hash table,也叫散列表),是根据key而直接进行访问的数据结构.也就是说,它通过把key映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放 ...
- 【温故而知新-Javascript】窗口效果 (全屏显示窗口、定时关闭窗口)
1.全屏显示窗口 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...
- 递归:codevs 1251 括号
codevs 1251 括号 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 计算乘法时,我们可以添加括号,来改变相乘的顺 ...
- OpenCV 之 数字图像
1 数字图像 数字图像可看作一个数值矩阵, 其中的每个元素代表一个像素点,如下图所示: 2 存储 M行N列图像的存储位数: b = M * N * k ( L=2k, l ∈ [0, L-1] ...
- POJ 2653 Pick-up sticks --队列,几何
题意: 按顺序扔木棒,求出最上层的木棒是哪些. 解法: 由于最上层的木棒不超过1000个,所以用一个队列存储最上层的木棒,每次扔出一个木棒后,都与队列中的木棒一一判断,看此木棒是否在某一最上层的木棒的 ...
- Android配置----小米手机通过wifi连接ADB调试Android应用
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3 ...
- 利用Clip制作打洞效果
起因 如上篇博文所说,连线原型需要在中间文字上下各留15像素的空白.设计师完成原型之后,问我有没有办法实现,我说,我能想到两种实现方式.其中一种就是上篇博文所说的OpacityMask.第二种就是使用 ...
- document.write和innerHTML的区别
document.write是直接写入到页面的内容流,如果在写之前没有调用document.open, 浏览器会自动调用open.每次写完关闭之后重新调用该函数,会导致页面被重写. innerHTML ...