[AngularJS]依赖注入

JS中的依赖注入,举个荔枝:

<button id="btn">click me</button>
<script>
  window.onload = function() {
    document.getElementById('btn').onclick = function(event) {
      alert(event.clientX);
    }
  }
</script>

1.回调函数的event就是依赖对象
2.回调函数有形参就是依赖注入(设置方法或者函数需要的参数的过程)

angularJS中也是一样的,告诉调用函数的对象模块,我需要哪些对象作为我的形参,所以,就是一个设置形参的过程

8263107-57b9d72ac67a72a5.png

image.png

 

8263107-63cfc385846e0178.png

image.png


上面这个例子中的代码虽然理想,但是它却把获得所依赖对象的大部分责任都放在了我们创建 SomeClass 的客户代码中。
为了分离“创建依赖”的职责,每个 Angular 应用都有一个 injector对象。这个 injector 是一个服务定位器,负责创建和查找依赖。(译注:当你的app的某处声明需要用到某个依赖时,Angular 会调用这个依赖注入器去查找或是创建你所需要的依赖,然后返回来给你用)

 

那么怎么告诉Angular模块,需要什么

依赖注释

(译注:此处注释非代码注释,应理解为依赖声明的方法)

那么,injector 是如何知道哪些服务需要被注入呢?

应用开发者需要提供 injector 需要使用的注释信息来解析依赖。Angular 之中,按照API文档说明,某些 API 方法需要通过 injector 调用。这样,injector 要知道得往这个方法中注入什么服务。下面是用服务名信息来进行注释的三种等价的方式,它们可以互用,按照你觉得适合的情况选用相应的方式。

推断依赖

最简单的获取依赖的方法是让你的函数的参数名直接使用依赖名。

1.  function  MyController($scope, greeter)  {
2.  ...
3.  }

给 injector 一个函数,它可以通过检查函数声明并抽取参数名可以推断需要注入的服务名。在上面的例子中,$scopegreeter 是两个需要被注入到函数中的服务。

虽然这种方式很直观明了,但是它对于压缩的 JavaScript 代码来说是不起作用的,因为压缩过后的 JavaScript 代码重命名了函数的参数名。这就让这种注释方式只对 pretotyping 和 demo级应用有用。

$inject 注释

为了让重命名了参数名的压缩版的 JavaScript 代码能够正确地注入相关的依赖服务。函数需要通过 $inject 属性进行标注,这个属性是一个存放需要注入的服务的数组。

1.  var  MyController  =  function(renamed$scope, renamedGreeter)  {
2.  ...
3.  }
4.  MyController['$inject']  =  ['$scope',  'greeter'];

在这种场合下,$inject 数组中的服务名顺序必须和函数参数名顺序一致。以上述代码段为例,$scope 将会被注入到 'renamed$scope',而 greeter 则是注入到 'renamedGreeter'。需要注意 $inject 注释是和真实的函数声明中的参数保持同步的。

这种注释方法对于控制器声明很有用处,因为它是把注释信息赋给了函数。

行内注释

有时候用 $inject 注释的方式不方便,比如标注指令的时候(译注:这里标注指令可以理解为告诉指令需要加载哪些服务依赖的说明)。

看下面的例子:

1.  someModule.factory('greeter',  function($window)  {
2.  ...
3.  });

由于需要一个临时的变量导致代码膨胀:

1.  var greeterFactory =  function(renamed$window)  {
2.  ...
3.  };

5.  greeterFactory.$inject =  ['$window'];

7.  someModule.factory('greeter', greeterFactory);

所以,第三种注释风格被引入,如下:

1.  someModule.factory('greeter',  ['$window',  function(renamed$window)  {
2.  ...
3.  }]);

记住,所有上面的三种依赖注释风格(译注:声明依赖的风格)是等价的,在 Angular 中任何支持依赖注入的地方都可以使用。

哪里使用DI

在 Angular 中,DI 无处不在。通常在控制器和工厂方法(译注:所谓的工厂方法个人理解为 Angular 中的API)中使用较多。

控制器中使用DI

控制器是负责应用操作逻辑的 JavaScript 类,推荐的在控制器中使用DI的方式是用数组标记风格,如下:

 someModule.controller('MyController', ['$scope', 'dep1', 'dep2', function($scope, dep1, dep2) {
    ...
    $scope.aMethod = function() {
      ...
    }
    ...
  }]);

如上那样,避免了在全局作用域内创建控制器,同时也避免了代码压缩时引起的注入问题。

工厂方法中使用DI

工厂方法负责创建 Angular 中的绝大多数对象。例如指令,服务,和过滤器等。工厂方法是注册在模块之下的,推荐的声明方式如下:

  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) {
      ...
    }]);

题外话:JS中的依赖注入类型

1.声明式依赖注入
注重结果,只要定义参数名称,就可以拿到结果。
2.命令式依赖注入
注重过程,定义参数名称,还有产生形参的过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值