angular js中的依赖注入是什么?有什么作用?

 

1.背景介绍

依赖注入式AngularJS的重要特性之一,依赖注入简化了Angular解析模块/组件之间依赖的过程。

 

什么是依赖注入

wiki 上的解释是:依赖注入(Dependency Injection,简称DI)是一种软件设计模式,在这种模式下, 一个或更多的依赖(或服务)被注入(或者通过引用传递)到一个独立的对象(或客户端)中,然后成为了该客户端状态的一部分。 该模式分离了客户端依赖本身行为的创建,这使得程序设计变得松耦合,并遵循了依赖反转和单一职责原则。与服务定位器模式形 成直接对比的是,它允许客户端了解客户端如何使用该系统找到依赖 .

2.知识剖析

ANGULAR依赖注入机制

AngularJS 提供了5个核心组件用来作为依赖注入:

value 
factory
service
provider
constant

$PROVIDE (供应商)

供应商==>泛指provider 
服务==>泛指service 
provider==>provider()方法创建的代码块
service==>service()方法创建的代码块

$provide服务负责告诉Angular如何创造一个新的可注入的代码块:即服务。服务会被叫做供应商的代码块来定义,我们可以使用$provide来创建一个供应商。

我们需要使用$provide中的provider()方法来定义一个供应商,同时也可以通过要求$provide被注入到一个应用的config函数中来获得$provide服务。

$PROVIDE

$provide负责告诉Angular如何创建新的可注入的事物,即服务。服务是被providers定义的,即当你用$provide创建的。通过$provide服务来定义provider,你可以通过在应用的配置函数中注入$provide来持有该服务。


                    angular.module(‘app’,[]).config(function($provide) {
                        $provide.provider('greeting', function() {
                            this.$get = function() {
                                return function(name) {
                                alert("Hello, " + name);
                                };
                            };
                        });
                    });    
                

在上面的例子中我们为一个服务定义了一个叫做greeting的新provider。 我们可以把一个叫做greeting的变量注入到任何可注入的函数中 (例如控制器)然后Angular就会调用这个provider的$get函数来返回这个服务的一个实例。

在上面的例子中,被注入的是一个函数, 它接受一个参数并且根据这个参数alert一条信息。我们可以像下面这样使用它:


                    app.controller('MyCtrl', function($scope, greeting) {
                        $scope.onClick = function() {
                            greeting('Ford Prefect');
                        };
                    });
                

定义供应商的方法

1、Constant

Constant定义常量,Constant定义的值不应该被改变,它可以被注入到任何地方,但是不能被装饰器(decorator)装饰


                    var app = angular.module('app', []);
                    app.config(function ($provide) {
                        $provide.constant('myConstant', 'The Matrix');
                    }); 
                

语法糖:


                    app.constant('myConstant', 'The Matrix');
                

2、VALUE

Value可以是string,number甚至function,它和constant的不同之处在于,它可以被修改,不能被注入到config中,但是它可以被decorator装饰


                    var app = angular.module('app', []);
                    app.config(function ($provide) {
                        $provide.value('myValue', 'The Matrix')
                    });
                    

语法糖:


                    app.value('myValue', 'The Matrix');
                

3、SERVICE

Service是一个可注入的构造器,在AngularJS中它是单例的,用它在Controller中通信或者共享数据都很合适. 在service里面可以不用返回东西,因为AngularJS会调用new关键字来创建对象。


                    var app = angular.module('app' ,[]);
                    app.config(function ($provide) {
                        $provide.service('myService', function () {
                            this.title = 'The Matrix';
                        });
                    });
                

语法糖:


                    app.service('myService', function () {
                        this.title = 'The Matrix';
                    });
                

4、FACTORY

Factory是一个可注入的function,它和service的区别就是:factory是普通function,而service是一个构造器(constructor), Angular在调用service时会用new关键字,而调用factory时只是调用普通的function,所以factory可以返回任何东西,而service可以不返回. factory可以返回任何东西,它实际上是一个只有$get方法的provider


                    var app = angular.module('app', []);
                    app.config(function ($provide) {
                        $provide.factory('myFactory', function () {
                            return {
                                title: 'The Matrix'
                            }
                        });
                    });
                

语法糖:


                    app.factory('movie', function () {
                        return {
                            title: 'The Matrix'
                        }
                    });
                

5、PROVIDER

provider是value、Service、Factory的提供者,除了constant其它都是provider的简写形式。 provider必须有一个$get方法,当然也可以说provider是一个可配置的factory


                app.provider('greeting', function() {
                    var text = 'Hello, ';
                    this.setText = function(value) {
                        text = value;
                    };
                    this.$get = function() {
                        return function(name) {
                            alert(text + name);
                        };
                };
                });
                app.config(function(greetingProvider) {
                greetingProvider.setText("Howdy there, ");
                });
                app.run(function(greeting) {
                greeting('Ford Prefect');
                });
                

注意这里config方法注入的是greetingProvider,上面定义了一个供应商叫greeting,但是注入到config中不能直接写greeting, 因为前文讲了注入的那个东西就是服务,是供应商提供出来的,而config中又只能注入供应商(两个例外是$provide和$injector), 所以用驼峰命名法写成greetingProvider,Angular就会帮你注入它的供应商。

factory和value等服务与provider都是提供服务,为什么还有人要使用provider。答案是provider允许我们进行一些配置。 在前面我们已经提到过当你通过provider(或者其他简写方法)创建一个服务时,你实际上创建了一个新的provider, 它将定义我们的服务如何被创建。这些provider可以被注入到config函数中,我们可以和它们进行一些交互。如上文例子:

AngularJS分两个阶段运行我们的用 – config阶段和run阶段。config阶段是我们设置任何的provider的阶段。 它也是我们设置任何的指令,控制器,过滤器以及其它东西的阶段。在run阶段,AngularJS会编译你的DOM并启动我们的应用。

总结

所有的供应商都只被实例化一次,也就说他们都是单例的; 除了constant,所有的供应商都可以被装饰器(decorator)装饰

value就是一个简单的可注入的值
service是一个可注入的构造器
factory是一个可注入的方法
decorator可以修改或封装其他的供应商,当然除了constant
provider是一个可配置的factory

3.常见问题

AngularJS依赖注入的方法

4.解决方案

1. 通过函数的参数进行推断式注入声明

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

2、显式注入声明

AngularJS提供了显式的方法来明确定义一个函数在被调用时需要用到的依赖关系。

通过这种方法声明依赖,即使在源代码被压缩、参数名称发生改变的情况下依然能够正常工作。

需要注意的地方: 
对于这种声明方式来讲,参数的顺序是十分重要的,因为$inject数组元素的顺序必须和注入的参数的顺序一一对应。

3、行内注入声明

AngularJS提供的行内注入方法实际上是一种语法糖,它与前面的提到的通过$inject属性进行声明的原理是一样的,但是允许我们在函数定义的时候从行内将参数传入,这种方法方便,简单,而且避免了在定义的过程中使用临时变量。

需要注意的地方: 
行内声明的方式允许我们直接传入一个参数数组,而不是一个函数。数组的元素是字符串,它们代表的是可以被注入到对象中的依赖名字,最后一个参数就是依赖注入的目标函数对象本身。

5.编码实战

6.扩展思考

AngularJS中的依赖注入有何优点?

一、模板功能强大丰富,并且是声明式的,自带了丰富的Angular指令;

二、是一个比较完善的前端MVC框架,包含模板,数据双向绑定,路由,模块化,服务,过滤器,依赖注入等所有功能;

三、依赖注入简化了组件之间处理依赖的过程(即解决依赖)。没有依赖注入,就不得不以某种方式自己查找$scope,很可能得使用全局变量。这虽然能够工作,但是不如AngularJS的依赖注入技术这么简单。

四、在开发中使用依赖注入的主要好处是AngularJS负责管理组件并在需要的时候提供给相应函数。依赖注入还能够为测试带来好处,因为它允许你使用假的或者模拟的对象来代替真实的组件,从而让开发者专注于程序的特定部分。

7.参考文献

参考一  玩转 AngualrJS 的依赖注入

参考二  详解AngularJS中的依赖注入

参考三  理解AngularJS中的依赖注入

8.更多讨论

问:AngularJS依赖注入的方法

答:

1. 通过函数的参数进行推断式注入声明

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

2、显式注入声明

AngularJS提供了显式的方法来明确定义一个函数在被调用时需要用到的依赖关系。

通过这种方法声明依赖,即使在源代码被压缩、参数名称发生改变的情况下依然能够正常工作。

需要注意的地方: 
对于这种声明方式来讲,参数的顺序是十分重要的,因为$inject数组元素的顺序必须和注入的参数的顺序一一对应。

3、行内注入声明

AngularJS提供的行内注入方法实际上是一种语法糖,它与前面的提到的通过$inject属性进行声明的原理是一样的,但是允许我们在函数定义的时候从行内将参数传入,这种方法方便,简单,而且避免了在定义的过程中使用临时变量。

需要注意的地方: 
行内声明的方式允许我们直接传入一个参数数组,而不是一个函数。数组的元素是字符串,它们代表的是可以被注入到对象中的依赖名字,最后一个参数就是依赖注入的目标函数对象本身。

问:什么时候使用service 

答:什么时都可以,service和factory功能相同

问:service和factory的区别

答:factory 是普通函数,可以返回任何东西。service 是构造函数,可以不反回东西。功能相同。

 

技能树.IT修真院   

 “我们相信人人都可以成为一个工程师,现在开始,找个师兄,带你入门,掌控自己学习的节奏,学习的路上不再迷茫”。

这里是技能树.IT修真院,成千上万的师兄在这里找到了自己的学习路线,学习透明化,成长可见化,师兄1对1免费指导。

快来与我一起学习吧~邀请链接 点击打开链接

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AngularJS ,通过使用依赖注入(Dependency Injection)的方式来注入服务。依赖注入是指在创建对象时,将该对象所依赖的其他对象通过构造函数、工厂函数、属性等方式传递进去的过程。 在 AngularJS ,$injector 服务用于实现依赖注入。$injector 会自动管理依赖项之间的关系,并将服务的实例注入到需要使用该服务的对象。 例如,我们要在一个名为 myController 的控制器使用 $scope 和 $http 服务,可以按照以下方式定义该控制器: ```javascript angular.module('myModule', []) .controller('myController', function($scope, $http) { // 使用 $scope 和 $http 服务 }); ``` 在上面的代码,我们使用 $scope 和 $http 参数来定义 myController 控制器的构造函数,$injector 会自动将 $scope 和 $http 服务的实例注入到 myController 控制器的构造函数。 需要注意的是,$injector 会根据参数名称来查找相应的服务,并将服务的实例注入到函数。因此,参数的名称必须与服务的名称保持一致,否则 $injector 就无法正确地将服务的实例注入到函数。 除了在控制器使用依赖注入外,我们还可以在服务、指令、过滤器等对象使用依赖注入。例如,在一个名为 myService 的服务使用依赖注入,可以按照以下方式定义该服务: ```javascript angular.module('myModule', []) .service('myService', function($http) { // 使用 $http 服务 }); ``` 在上面的代码,我们使用 $http 参数来定义 myService 服务的构造函数,$injector 会自动将 $http 服务的实例注入到 myService 服务的构造函数。 需要注意的是,$injector 会根据参数名称来查找相应的服务,并将服务的实例注入到函数。因此,参数的名称必须与服务的名称保持一致,否则 $injector 就无法正确地将服务的实例注入到函数

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值