AngularJS學習筆記之依賴注入詳解_AngularJS

來源:互聯網
上載者:User

     最近在看AngularJS權威指南,由於各種各樣的原因(主要是因為我沒有money,好討厭的有木有......),於是我選擇了網上下載電子版的(因為它不要錢,哈哈...),字型也蠻清晰的,總體效果還不錯。但是,當我看到左上方的總頁碼的時候,479頁....479....479....俺的小心臟被擊穿了二分之一有木有啊,上半身都石化了有木有啊,那種特別想學但是看到頁碼又不想學的糾結的心情比和女朋友吵架了還複雜有木有啊,我平常看的電子書百位元都不大於3的好伐! 哎,原諒我吧,我應該多看幾本新華字典習慣習慣的...

不過幸好在看電子書之前,我已經稍微有點基礎了,之前看著視頻學習了一些,從雙向資料繫結到服務,然後到指令系統,都多多少少有些接觸。並且在一次web專選課結課作業當中,通過前端的AngularJS和背景NodeJS加Mongoose搭建了一個簡易學生班級管理系統。因為沒有錢,所以只能放在GitHub了,GitHub地址: 學生管理系統,歡迎來fork哈,下面進入正題...

=======================================請叫我華麗的分割線=======================================

     

一個對象通常有三種方式可以獲得對其依賴的控制權:

  (1) 在內部建立依賴;
  (2) 通過全域變數進行引用;
  (3) 在需要的地方通過參數進行傳遞。

依賴注入是通過第三種方式實現的。其餘兩種方式會帶來各種問題,例如汙染全域範圍,使隔離變得異常困難等。依賴注入是一種設計模式,它可以去除對依賴關係的寫入程式碼,從而可以在運行時改變甚至移除依賴關係。

  在運行時修改依賴關係的能力對測試來講是非常理想的,因為它允許我們建立一個隔離的環境,從而在測試環境可以使用類比的對象取代生產環境中的真實對象。

 從功能上看,依賴注入會事先自動尋找依賴關係,並將注入目標告知被依賴的資源,這樣就可以在目標需要時立即將資源注入進去。

 在編寫依賴於其他對象或庫的組件時,我們需要描述組件之間的依賴關係。在運行期,注入器會建立依賴的執行個體,並負責將它傳遞給依賴的消費者。

// 出自Angular文檔的優秀樣本function SomeClass(greeter) {this.greeter = greeter;}SomeClass.prototype.greetName = function(name) {this.greeter.greet(name);};//注意,範例程式碼在全域範圍上建立了一個控制器,這並不是一個好主意,這裡只是為了方便示範。

SomeClass 能夠在運行時訪問到內部的 greeter ,但它並不關心如何獲得對 greeter 的引用。為了獲得對 greeter 執行個體的引用, SomeClass 的建立者會負責構造其依賴關係並傳遞進去。

基於以上原因,AngularJS使用 $injetor (注入器服務)來管理依賴關係的查詢和執行個體化。事實上, $injetor 負責執行個體化AngularJS中所有的組件,包括應用的模組、指令和控制器等。

在運行時,任何模組啟動時 $injetor 都會負責執行個體化,並將其需要的所有依賴傳遞進去。

例如下面這段代碼。這是一個簡單的應用,聲明了一個模組和一個控制器:

angular.module('myApp', []).factory('greeter', function() {return {greet: function(msg) {alert(msg);}}}).controller('MyController',function($scope, greeter) {$scope.sayHello = function() {greeter.greet("Hello!");};});

當AngularJS執行個體化這個模組時,會尋找 greeter 並自然而然地把對它的引用傳遞進去:

<div ng-app="myApp"><div ng-controller="MyController"><button ng-click="sayHello()">Hello</button></div></div>

而在內部,AngularJS的處理過程是下面這樣的:

// 使用注入器載入應用var injector = angular.injector(['ng', 'myApp']);// 通過注入器載入$controller服務var $controller = injector.get('$controller');// 載入控制器並傳入一個範圍,同AngularJS在運行時做的一樣var scope = injector.get('$rootScope').$new();var MyController = $controller('MyController', {$scope: scope});

上面的代碼中並沒有說明是如何找到 greeter 的,但是它的確能正常工作,因為 $injector會負責為我們尋找並載入它。

AngularJS通過 annotate 函數,在執行個體化時從傳入的函數中把參數列表提取出來。在Chrome的開發人員工具中輸入下面的代碼可以查看這個函數:

> injector.annotate(function($q, greeter) {}) ["$q", "greeter"]

在任何一個AngularJS的應用中,都有 $injector 在進行工作,無論我們知道與否。當編寫控制器時,如果沒有使用 [] 標記或進行顯式的聲明, $injector 就會嘗試通過參數名推斷依賴關係。

推斷式注入聲明 

如果沒有明確的聲明,AngularJS會假定參數名稱就是依賴的名稱。因此,它會在內部調用函數對象的 toString() 方法,分析並提取出函數參數列表,然後通過 $injector 將這些參數注入進對象執行個體。注入的過程如下:

injector.invoke(function($http, greeter) {});

請注意,這個過程只適用於未經過壓縮和混淆的代碼,因為AngularJS需要原始未經壓縮的參數列表來進行解析。有了這個根據參數名稱進行推斷的過程,參數順序就沒有什麼重要的意義了,因為AngularJS會協助我們把屬性以正確的順序注入進去。

顯式注入聲明

AngularJS提供了顯式的方法來明確定義一個函數在被調用時需要用到的依賴關係。通過這種方法聲明依賴,即使在原始碼被壓縮、參數名稱發生改變的情況下依然能夠正常工作。可以通過$inject 屬性來實現顯式注入聲明的功能。函數對象的 $inject 屬性是一個數組,數組元素的類型是字串,它們的值就是需要被注入的服務的名稱。

下面是範例程式碼:

var aControllerFactory =function aController($scope, greeter) {console.log("LOADED controller", greeter);// ……控制器};aControllerFactory.$inject = ['$scope', 'greeter']; // Greeter服務console.log("greeter service");}// 我們應用的控制器angular.module('myApp', []).controller('MyController', aControllerFactory).factory('greeter', greeterService);// 擷取注入器並建立一個新的範圍var injector = angular.injector(['ng', 'myApp']),controller = injector.get('$controller'),rootScope = injector.get('$rootScope'),newScope = rootScope.$new();// 調用控制器controller('MyController', {$scope: newScope});

對於這種聲明方式來講,參數順序是非常重要的,因為 $inject 數組元素的順序必須和注入參數的順序一一對應。這種聲明方式可以在壓縮後的代碼中運行,因為聲明的相關資訊已經和函數本身綁定在一起了。

行內注入聲明

AngularJS提供的注入聲明的最後一種方式,是可以隨時使用的行內注入聲明。這種方式其實是一個文法糖,它同前面提到的通過 $inject 屬性進行注入聲明的原理是完全一樣的,但允許我們在函數定義時從行內將參數傳入。此外,它可以避免在定義過程中使用臨時變數。

在定義一個AngularJS的對象時,行內聲明的方式允許我們直接傳入一個參數數組而不是一個函數。數組的元素是字串,它們代表的是可以被注入到對象中的依賴的名字,最後一個參數就是依賴注入的目標函數對象本身。

樣本如下:

angular.module('myApp').controller('MyController', ['$scope', 'greeter', function($scope, greeter) {}]);

由於需要處理的是一個字串組成的列表,行內注入聲明也可以在壓縮後的代碼中正常運行。通常通過括弧和聲明數組的 [] 符號來使用它。

以上這篇AngularJS 依賴注入就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援雲棲社區。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.