AngularJS权威指南-依赖注入

《AngularJS 权威教程》读书笔记,第十三章——依赖注入。

简介

一个对象通常有三种方式可以获得对其依赖的控制权:

  1. 在内部创建依赖(缺点:手动创建,太麻烦)
  2. 通过全局变量进行引用(缺点:需要创建一大批全局变量,污染全局作用域)
  3. 在需要的地方通过参数进行传递(依赖注入,目前最佳的方式)

AngularJS 使用 $inject(注入器服务)来管理依赖关系的查询和实例化。事实上,$inject 负责实例化 AngularJS 中所有的组件,包括应用的模块、指令和控制器等。
在运行时,任何模块启动时 $inject 都会负责实例化,并将其需要的所有依赖传递进去。
当编写控制器时,如果没有使用 [] 标记或进行显示的声明,$injector 就会尝试通过参数名推断依赖关系。

推断式注入声明

如果没有明确的声明,AngularJS 会假定参数名称就是依赖的名称。它会在内部调用函数对象的 toString() 方法,分析并提取出函数参数列表,通过 $injector 将这些参数注入进对象实例。示例:

1
2
3
4
angular.module('myApp', [])
.controller('MyController', function($scope, greeter){
});

所以这个过程只适用于未经压缩和混淆的代码,因为 AngularJS 需要原始未经压缩的参数列表来进行解析,而压缩和混淆为了减少源文件的体积通常会将参数名改写成简单的字符,也会删除空格、空行和注释等。

显示注入声明

AngularJS 提供了显示的方法来明确定义一个函数在被调用时需要用到的依赖关系。通过这种方法声明依赖,即使在源代码被压缩、参数名称发生改变的情况下依然能够正常工作。示例:

1
2
3
4
5
6
7
8
9
10
var aControllerFactory =
function aController($scope, greeter){
console.log('LOADED controller', greeter);
};
aControllerFactory.$inject = ['$scope', 'greeter'];
angular.module('myApp', [])
.controller('MyController', aControllerFactory)
.factory('grreeter', greeterService);

行内注入声明

AngularJS 提供的行内注入声明其实是一种语法糖,它同显示注入声明的原理是一样的,所以行内注入声明也可以在压缩后的代码中正常运行。示例:

1
2
3
4
angular.module('myApp')
.controller('MyController', ['$scope', 'greeter', function($scope, greeter){
}]);

$injector API

  1. annotate():返回值是一个由服务名称组成的数组:用法没看懂
  2. get():返回一个服务的实例
  3. has():返回一个布尔值,在 $injector 能够从自己的注册列表中找到对应的服务时返回 true,否则返回 false
  4. instantiate():instantiate() 方法可以创建某个 JavaScript 类型的实例,它会通过 new 操作符调用构造函数,并将所有参数都传递给构造函数
  5. invoke():该方法会调用方法并从 $injector 中添加方法参数

ngMin

当我们在写代码时使用了推断式声明依赖的方式的话,ngMin 这个预压缩工具可以将代码转换为行内注入声明的方式。