AngularJS 依赖注入

本篇文章参考自AngularJS权威教程。

1.简介

  一个对象通常有三种方式可以获得对其依赖的控制权。依赖注入是通过第三种方式实现的,其优点在于去除对依赖关系的硬编码,可以在运行时改变甚至移除依赖关系。第一种方法和第二种,调用者和被调用者或和生产被调用者的工厂耦合在一起,第二种还会污染全局作用域。

  • 在内部创建依赖。

    当你需要斧子来砍木头时,你自己造一把斧子或是去购买一把斧子。造一把斧子相当于调用者创造被调用者,买一把斧子相当于简单工厂模式,调用者通过工厂方法获得被调用者。

  • 通过全局变量进行引用。

    外面的世界已经有很多斧子,你找到其中一把斧子并使用它。

  • 在需要的地方通过参数进行传递。

    当你需要斧子的时候,会有特定的人把斧头递给你。

2.注入声明方式

  AngularJS一共提供了三种注入声明方式。

  • 推断式注入声明

    如果没有明确的声明,AngularJS会假定参数名称就是依赖名称。它会使用$injector将这些参数注入进对象实例。我们不推荐使用这种方式,因为一旦代码被压缩(参数名被替换成简单的字符),那么会导致注入失败。

app.controller("myController",function($scope,myservice) {
    //AngularJS会假设依赖名称就是\$scope,myservice
});
  • 显式注入声明

    这种方式能够明确定义函数被调用时所需要的依赖关系。我们只要为函数对象新增$inject属性,值为一个字符串数组,数组的每一个元素就是依赖名称,注意数组元素的顺序必须和注入参数的顺序一个一个对应,因为这种方式参数名称没有关系,因此也不怕代码压缩。

var myFunction = function(a,b) {
};
myFunction.$inject = ["$scope","myService"]; //注入依赖,现在参数a代表$scope服务,参数b代表myService自定义服务
app.controller("myController",myFunciton");
  • 行内注入声明
    行内注入声明是显式注入声明的一种语法糖,它允许我们在定义一个AngularJS对象的时候直接传入一个参数数组而不是一个函数,数组的最后一项是依赖注入的目标函数本身,其他项是字符串,依次对应着该函数注入的依赖名字,同样应该注意数组元素的顺序和注入参数的对应。
app.controller("myController",["$scope","myService",function(a,b) {
    //这里a代表\$scope服务,b代表myService服务
});

3.$injector

  AngularJS使用注入器服务$injector来管理依赖关系的查询和实例化,所有的组件,包括应用的模块、指令、控制器和服务都是由$injector实例化的。使用angular的injector()方法可以获取$injector服务,该方法接受一个可选参数,参数值为一个数组,包含了需要绑定的模块,另外每次调用该方法,返回的都是不同的注入器对象。

var $injector = angular.injector(); //没有绑定任何模块的注入器,无法通过get方法得到任何服务实例
var $injector = angular.injector(["firstApp","secondApp"]); //绑定了firstApp和secondApp模块的注入器,能通过get方法得到这两个模块的服务实例

  $injector有以下API。

  • annotate()
    使用annotate()方法可以知道哪些服务会在函数被调用时被注入进去。annotate()方法接受一个函数作为参数,返回值是一个由服务名称组成的数组,这些服务会在实例化时被注入到目标函数中。
var myFunction = function(a,b) {
};
var $injector = angular.injector();
console.log($injector.annotate(myFunction)); //["a","b"],在没有显式声明依赖时,简单的返回参数列表
myFunction.$inject = ["$scope","myService"];
console.log($injector.annotate(myFunction)); //["$scope","myService"],显式声明依赖后,与参数无关,与函数对象的$inject属性相同
  • get()
    get()接受一个字符串作为参数,返回一个名称是该字符串的服务实例。
var app = angular.module("myApp",[]);
app.factory("myService",function() {
    return {
        name:"张三"
    };
});
var $injector = angular.injector(["myApp"]);
console.log($injector.get("myService")); //Object {name:"张三"}
  • has()
    has()接受一个字符串作为参数,如果$injector能够从自己的注册列表找到该名称的服务返回true,否则返回false。
var app = angular.module("myApp",[]);
app.factory("myService",function() {
    return {
        name:"张三"
    };
});
var $injector = angular.injector();
console.log($injector.has("myService")); //false
$injector = angular.injector(["myApp"]);
console.log($injector.has("myService")); //true
  • instantiate()
    instantiate()方法用来创建某个JavaScript类型的实例。它会通过new操作符调用构造函数,并将所有参数都传给构造函数。它可以接受两个参数,第一个参数Type是函数,代表用来实例对象的构造函数,第二个可选参数是对象,只是提供了一种传递参数的方式。
var app = angular.module("myApp",[]);
function myObject (name,age) { //构造函数
    this.name = name;
    this.age = age;
}
var $injector = angular.injector();
console.log($injector.instantiate(myObject,{name:"张三",age:15})); //myObject {name:"张三",age:15}
  • invoke()
    invoke()会调用方法并从$injector中添加方法参数。
参数类型含义
fnfunction要调用的函数,invoke()函数返回值就是该函数的返回值
selfobject(可选)允许我们设置调用方法的this参数
localsobject(可选)提供另一种传递参数的方式
var app = angular.module("myApp",[]);
function myObject (age) {
    this.age = age;
    return this.name+this.age;
}
var $injector = angular.injector();
console.log($injector.invoke(myObject,{name:"张三"},{age:18})); //张三18this.name是通过第二个参数直接设置的,this.age是通过第三个参数传进去在函数中设置的,invoke函数的返回值就是第一个参数的返回值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值