1.依賴注入(DI)
DI是一個(gè)設(shè)計(jì)模式,處理組件如何獲取依賴。
angular中 injector子系統(tǒng)專門負(fù)責(zé)創(chuàng)建組件,解析依賴,并且提供給請求的組件。
2.使用 DI
DI 在angular中廣泛使用。你可以用它定義模塊或者給模塊提供run或者config塊的時(shí)候。
- service,directive,filter 和 animation 這些組件都是可注入的工廠方法或者構(gòu)造方法。
- Controller通過一個(gè)構(gòu)造函數(shù)定義。這個(gè)構(gòu)造函數(shù)可以被注入 服務(wù)或 value 依賴組件,也可以以依賴的方式提供給其他組件。
- run 接受一個(gè)函數(shù),這個(gè)函數(shù)可以被注入service,value,constant 組件。
- config 接受一個(gè)函數(shù),這個(gè)函數(shù)可以被注入 provider, constant 組件作為依賴。不能注入 service 或value到配置階段。
3.工廠方法
定義 directive, service, filter都是通過工廠方法。這些工廠方法注冊在模塊上面。
angular.module('myModule', [])
.factory('serviceId', ['depService', function(depService) {
// ...
}])
.directive('directiveName', ['depService', function(depService) {
// ...
}])
.filter('filterName', ['depService', function(depService) {
// ...
}]);
4.模塊方法
我們可以指定在 運(yùn)行階段 和 配置階段 的函數(shù)。這些函數(shù)可以注入依賴。
angular.module('myModule', [])
.config(['depProvider', function(depProvider) {
// ...
}])
.run(['depService', function(depService) {
// ...
}]);
5.控制器
控制器是類或構(gòu)造函數(shù)。他負(fù)責(zé) 給聲明的模板 提供應(yīng)用程序的行為。
someModule.controller('MyController', ['$scope', 'dep1', 'dep2', function($scope, dep1, dep2) {
...
$scope.aMethod = function() {
...
}
...
}]);
和服務(wù)不一樣,控制器可以有多個(gè)實(shí)例。
然而,額外的依賴,控制器可以拿到
- $scope:控制器和dom有關(guān)聯(lián)并且可以訪問響應(yīng)的scope。其他組件就只能訪問$rootScope
- 解析:如果一個(gè)控制器作為路由的一部分進(jìn)行實(shí)例化。任何路由解析到的值可以注入控制器。
6.依賴注入
angular通過注入器來調(diào)用 某個(gè)函數(shù)。你需要給這些函數(shù)標(biāo)注以便注入器知道需要注入什么服務(wù)。
有三種方式來標(biāo)注你的代碼
使用行內(nèi)數(shù)組的方式來標(biāo)注(推薦)
用$inject 來標(biāo)注
通過函數(shù)參數(shù)隱含的方式
7.行內(nèi)數(shù)組方式
someModule.controller('MyController', ['$scope', 'greeter', function($scope, greeter) {
// ...
}]);
8.通過$inject 屬性
var MyController = function($scope, greeter) {
// ...
}
MyController.$inject = ['$scope', 'greeter'];
someModule.controller('MyController', MyController);
9.為什么要依賴注入
有三種方式可以讓一個(gè)組件獲得依賴
- 組件直接調(diào)用 new 操作符來創(chuàng)建一個(gè)依賴。
- 組建自己在全局變量里面尋找依賴。
- 組件可以在需要的時(shí)候讓依賴傳進(jìn)來。
前兩項(xiàng)通過創(chuàng)建和查找引用不太好,因?yàn)檫@樣會導(dǎo)致代碼太僵硬。這會使你很難再修改依賴。
第三種才可行,因?yàn)樗褜ふ乙蕾嚨呢?zé)任從組建里剝離了。
function SomeClass(greeter) {
this.greeter = greeter;
}
SomeClass.prototype.doSomething = function(name) {
this.greeter.greet(name);
}
上面這個(gè)例子,SomeClass不用關(guān)心創(chuàng)建或定位依賴,他只用簡單的使用greeter就行了。
這很理想,但是他把獲取依賴的責(zé)任推給了構(gòu)建 SomeClass的那些代碼。
要管理依賴的創(chuàng)建,每個(gè)angular應(yīng)用程序都有一個(gè)注入器。這個(gè)注入器是一個(gè)服務(wù)定位著,他負(fù)責(zé)創(chuàng)建和查找依賴。
創(chuàng)建一個(gè)新的注入器,這個(gè)注入器可以提供定義在myModule上面的組件。
var injector = angular.injector(['ng', 'myModule']);
var greeter = injector.get('greeter');
請求請求依賴解析解決了硬編碼的問題。但是也意味著應(yīng)用程序需要被傳進(jìn)來一個(gè)注入器。
當(dāng)angular編譯模板的時(shí)候,
<div ng-controller="MyController">
<button ng-click="sayHello()">Hello</button>
</div>
function MyController($scope, greeter) {
$scope.sayHello = function() {
greeter.greet('Hello World');
};
}
injector.instantiate(MyController);
這是最好的結(jié)果。程序代碼只用簡單的聲明依賴,而不用處理注入。這也沒有違反lod原則。
lod原則:面向?qū)ο笾?,對象對其他地方知道的越少越好?/p>