依赖注入,是一种软件设计模式,应DIP依赖倒置原则,描述组件之间高层组件不应该依赖于底层组件。依赖注入简化了Angular解析模块/组件之间依赖的过程。在AngularJS中,依赖注入无孔不入。
依赖注入贯穿于Angular, 可以在定义组件例如directive,factory,filter,provider,controller,或给模提供 run
和config
代码块时候使用它。
三种依赖注解的方法
1:内敛数组(优选)
angular.module('myApp',[]).controller('myControl',['$scope',function($scope) {
}])
2:通过$inject 属性注解
var myControl=function($scope) {
}
myControl.$inject=['$scope'];
angular.module('myApp',[]).controller('myControl',myControl);
3:隐式标注,通过函数参数名,自动寻找,这种方法在js代码被压缩时容易出问题 (在严格模式下,加上ng-strict-di,那么这种模式就报错)
angular.module('myApp',[]).controller('myControl',function($scope) {
})
3 种提供服务的方法
1:factory,也就是我们创建一个带有方法和属性的对象,我可以把它注入到其他组件当中。
代码如下: 在html标签上写上ng-app='myApp'
<body ng-controller='myControl' >
<div class='container'>
<button class='btn btn-success bt-lg' ng-click='targetFunction()' >click</button>
<button class='btn btn-info bt-lg' ng-click='targetName()' >click</button>
</div>
</body>
angular.module('myApp',[]).controller('myControl' ,['$scope','target' ,function($scope,target) {
//将target服务注入到controller中
$scope.targetFunction=function() {
alert(target.targetFucntion());//使用它
}
$scope.targetName=function() {
alert(target.targetName);//使用它
}
}])
.factory('target',[function() {//使用factory生成一个服务叫做target,
var factory={};//定义一个对象
factory.targetName='I am a string!'//在对象定义一个属性
factory.targetFucntion=function() {//在对象定义一个方法
return 'I am a function!'
}
return factory;//返回对象
}])
当点击第一个按钮显示
点击第二个
2:serviece 相当于我们new一个对象,我们需要做的事情就是在this上面加上属性和方法。
代码如下: 在html标签上写上ng-app='myApp'
angular.module('myApp',[]).controller('myControl' ,['$scope','target' ,function($scope,target) {
//将target服务注入到controller中
$scope.targetFunction=function() {
alert(target.targetFucntion());//使用它
}
$scope.targetName=function() {
alert(target.targetName);//使用它
}
}])
.service('target',[function() {//使用service生成一个服务叫做target,
this.targetName='I am a string!'
this.targetFucntion=function() {
return 'I am a function!'
}
}])
当点击第一个按钮显示
点击第二个
service()方法很适合使用在功能控制比较多的service里面
3:provider provider必须提供一个this.$get方法,在$get方法里面和factory一样,也就是我们创建一个带有方法和属性的对象。
angular.module('myApp',[]).controller('myControl' ,['$scope','target' ,function($scope,target) {
//将target服务注入到controller中
$scope.targetFunction=function() {
alert(target.targetFunction());//使用它
}
$scope.targetName=function() {
alert(target.targetName);//使用它
}
}])
.provider('target',[function() {//使用provider生成一个服务叫做target,
this.$get=function(){
var service={};
service.targetName='I am a string!' ;
service.targetFunction=function() {
return 'I am a function!'
}
return service;
}
}])
当点击第一个按钮显示
点击第二个
provider在三个当中是唯一一个可以注入到config里面的。
Angular在加载模块时经过两个阶段:config和run。传入config函数的方法会在当前模块加载时执行;传入run函数的方法会在所有模块加载结束后执行。因此,在config阶段即可配置多个provider,但是在config阶段,只有provider可以注入,因此自定义的service无法注入到config中。这也好理解,因为config阶段是对service进行配置的而不是使用service本身。
假如你的服务需要在注入之前配置,那么就得使用provider。需要注意的是:在config函数里注入provider时,名字应该是:providerName+Provider.
代码如下: 在html标签上写上ng-app='myApp'
angular.module('myApp',[]).controller('myControl' ,['$scope','target' ,function($scope,target) {
//将target服务注入到controller中
$scope.targetFunction=function() {
alert(target.targetFunction());//使用它
}
$scope.targetName=function() {
alert(target.targetName);//使用它
}
}])
.provider('target',[function() {//使用provider生成一个服务叫做target,
var name='';
this.setName=function(n) {//设置一个配置方法
name=n;
}
this.$get=function(){
var service={};
service.targetName=name ;
service.targetFunction=function() {
return 'I am a function!'
}
return service;
}
}])
.config(function(targetProvider){//在服务之前进行配置,
targetProvider.setName('I am a string!');
})
当点击第一个按钮显示
点击第二个
angular.module('myApp',[]).controller('myControl' ,['$scope' ,function($scope) {
}])
.provider('target',[function() {//使用provider生成一个服务叫做target,
console.log('666');
}])
在controller当中,我并没有注入target服务,但是这个服务已经实例化了。结果如图:
当换成factory和service,则不可以,并没有输出666
在服务被注入前,只有provider被实例化,那么就很容易先到factory,service不能配置了吧!因为别人都还没有实例化。
这里还有几点需要注意:
controller比较特殊,它虽然也是一种组件,但是特别之处是它与某个DOM元素关联,因此可以注入$scope ,controller不能注入到其他组件当中。
而其他组件只能注入$rootScope (根作用域)$rootScope 可作用于整个应用中。是各个 controller 中 scope 的桥梁。用 rootscope 定义的值,可以在各个 controller 中使用。