angular.js的依賴注入解析


本教程使用AngularJS版本:1.5.3

       angularjs GitHub: https://github.com/angular/angular.js/

       AngularJs下載地址:https://angularjs.org/

         用有過spring的人都知道,Spring的核心思想就是DI(依賴注入,Dependency Injection)和IOC(控制反轉 Invension of Controller),AngularJS的service其實就是用到了這里的DI思想,那么什么叫做DI?所謂DI,就是指對象是被動接受依賴類而不是自己主動去找,換句話說就是指對象不是從容器中查找它依賴的類,而是在容器實例化對象的時候主動將它依賴的類注入給它。我個人的理解就是,你在實例化一個類時,它會自動去實例化它里面所用到的其它實例。所以這就叫依賴注入。在Angular里面,services作為單例對象在需要到的時候被創建,只有在應用生命周期結束的時候(關閉瀏覽器)才會被清除。而controllers在不需要的時候就會被銷毀了。

       AngualrJs中可用來注入的有三種類型,service、factory、provider,這三種寫法不樣,用法也都不一樣。其中,service只實例化一次,其實就是單例模式的思想。無論我們在什么地方注入我們的service,將永遠使用同一個實例。所以對很多在controller層中的操作就可以放到serivce層中去。AngularJS提供例如許多內在的服務,如:$http, $route, $window, $location等。每個服務負責例如一個特定的任務,$http是用來創建AJAX調用,以獲得服務器的數據。 $route用來定義路由信息等。內置的服務總是前綴$符號。

      其中,三者的關系可以看成是下圖:

一、Service使用詳解

(1)定義

一個學用的service用法如下:

一般直接用this來操作數據、定義函數。

 

[html]  view plain  copy
 
  1. app.service('myService', function() {  
  2.     var privateValue = "I am Private";  
  3.     this.variable = "This is public";  
  4.     this.getPrivate = function() { return privateValue;  
  5. };  
  6. });  

 

(2)AngularJS中使用DI添加Service的三種方法 
方式1(內聯注解,推薦使用):

[html]  view plain  copy
 
  1. app.controller('myController', ['$scope', 'dateFilter', function ($scope, dateFilter) { }]);  

方式2($inject注解):

[html]  view plain  copy
 
  1.  var MyController = function($scope, dateFilter) {}  
  2. MyController.$inject = ['$scope', 'dateFilter'];  
  3. someModule.controller('MyController', MyController);  

方式3(隱式注解,不推薦使用):

[html]  view plain  copy
 
  1. app.controller('myController', function ($scope, dateFilter) { });  

推薦使用方式1的理由是:
寫法上比方法2更簡單明了
比方法3更可靠(由於Javascript可以被壓縮,AngularJS又是通過解析服務名稱找到對應Service的,因此Javascript壓縮之后AngularJS將無法找到指定的Service,但字符串不會被壓縮,因此單獨以字符串指定Service的名稱可以避免這個問題)
使用方式1或方式2的注意點:
由於上述第二點原因,AngularJS在編譯Html時,由$injector將數組中Service的名稱與方法體中的Service進行一一映射。這種映射關系必須遵守由AngularJS的約定:
數組中Service名稱的個數必須與方法體中Service名稱的個數一致
數組中Service的順序必須與方法體中Serivce的順序一致

 

(3)什么時候適合使用service()方法
service()方法很適合使用在功能控制比較多的service里面
注意:需要使用.config()來配置service的時候不能使用service()方法

(4)service使用實例 

一個完整實例:

 

[html]  view plain  copy
 
  1. <!DOCTYPE html>  
  2. <html lang="zh" ng-app="myApp">  
  3. <head>  
  4.     <meta charset="UTF-8">  
  5.     <title>AngularJS學習</title>  
  6.     <script type="text/javascript" src="./1.5.3/angular.min.js"></script>  
  7. </head>  
  8. <body>  
  9.     <div ng-controller="myCtrl">  
  10.         <button ng-click="getPrivate()">按鈕一</button>  
  11.         <button ng-click="getPUbluc()">按鈕二</button>  
  12.     </div>  
  13.     <div ng-controller = "myCtrl2">  
  14.     </div>  
  15. </body>  
  16. <script type="text/javascript">  
  17. var app = angular.module('myApp', []);  
  18. app.controller('myCtrl', function($scope, myService) {  
  19.     $scope.getPrivate = function() {  
  20.         alert(myService.getPrivate());  
  21.     };  
  22.     $scope.getPUbluc = function() {  
  23.         alert(myService.variable);  
  24.     };  
  25. });  
  26. app.controller('myCtrl2', function($scope, myService) {  
  27.   
  28. });  
  29. app.service('myService', function() {  
  30.      console.log('instance myService');  
  31.     var privateValue = "I am Private";  
  32.     this.variable = "This is public";  
  33.     this.getPrivate = function() {  
  34.         return privateValue;  
  35.     };  
  36. });  
  37. </script>  
  38. </html>  

效果如下:

另外,從這里可以看到兩個controller注入同一個service,但是最終只實例化了一次!
 
注意:seivce定義的服務不能在.config中使用!只有provider定義的才可以
 

二、Factory使用詳解

Factory 一般就是創建一個對象,然后在對這個對象添加方法與數據,最后將些對象返回即可。然后注入到Controller層中即可。
 
使用實例:
[html]  view plain  copy
 
  1. <!DOCTYPE html>  
  2. <html lang="zh" ng-app="myApp">  
  3. <head>  
  4.     <meta charset="UTF-8">  
  5.     <title>AngularJS學習</title>  
  6.     <script type="text/javascript" src="./1.5.3/angular.min.js"></script>  
  7. </head>  
  8. <body>  
  9.     <div ng-controller="myCtrl">  
  10.         <button ng-click="getPrivate()">按鈕一</button>  
  11.         <button ng-click="getPUbluc()">按鈕二</button>  
  12.     </div>  
  13.     <div ng-controller = "myCtrl2">  
  14.     </div>  
  15. </body>  
  16. <script type="text/javascript">  
  17. var app = angular.module('myApp', []);  
  18. app.controller('myCtrl', function($scope, myFactory) {  
  19.     $scope.getPrivate = function() {  
  20.         alert(myFactory.getPrivate());  
  21.     };  
  22.     $scope.getPUbluc = function() {  
  23.         alert(myFactory.variable);  
  24.     };  
  25. });  
  26. app.controller('myCtrl2', function($scope, myFactory) {  
  27.   
  28. });  
  29. app.factory('myFactory', function() {  
  30.     console.log('instance myFactory');  
  31.     var factory = {};  
  32.     var privateValue = "I am Private";  
  33.     factory.variable = "This is public";  
  34.     factory.getPrivate = function() {  
  35.         return privateValue;  
  36.     };  
  37.     return factory;  
  38. });  
  39. </script>  
  40. </html>  
效果:
從下面可以看到只實例化了一次,兩下Controller注入同一個factory,但是最終只實例化了一次!
記得一定要return一個Object對象,否則會報如下錯誤:
 
AngularJS中的Services:

三、provider使用詳解

    $provide服務負責告訴Angular如何創造一個新的可注入的東西:即服務。服務會被叫做供應商的東西來定義,你可以使用$provide來創建一個供應商。你需要使用$provide中的provider()方法來定義一個供應商,同時你也可以通過要求$provide被注入到一個應用的config函數中來獲得$provide服務。使用方法是返回一個$get函數,注意在config階段,只有provider能被注入。其它用法和service一樣。
下面是一個實例。
[html]  view plain  copy
 
  1. <!DOCTYPE html>  
  2. <html lang="zh" ng-app="myApp">  
  3. <head>  
  4.     <meta charset="UTF-8">  
  5.     <title>AngularJS學習</title>  
  6.     <script type="text/javascript" src="./1.5.3/angular.min.js"></script>  
  7. </head>  
  8. <body>  
  9.     <div ng-controller="myCtrl1">  
  10.         <button ng-click = "onclick1()">請點擊我1</button>  
  11.     </div>  
  12.     <div ng-controller="myCtrl2">  
  13.          <button ng-click = "onclick2()">請點擊我2</button>  
  14.     </div>  
  15. </body>  
  16. <script type="text/javascript">  
  17. var app = angular.module('myApp', []);  
  18. app.controller('myCtrl1', function($scope, testProvider) {  
  19.     $scope.onclick1 = function() {  
  20.         testProvider("林炳文Evankaka");  
  21.     };  
  22. });  
  23. app.controller('myCtrl2', function($scope , testProvider) {  
  24.       $scope.onclick2 = function() {  
  25.         testProvider("我到底是誰");  
  26.     };  
  27. });  
  28.   
  29. app.provider('testProvider', function(){  
  30.     console.log('instance testProvider');  
  31.     var f = function(name) {  
  32.        alert("Hello, " + name);  
  33.     };  
  34.     this.$get = function(){ //一定要有!  
  35.       return f;  
  36.    };  
  37. });  
  38. </script>  
  39. </html>  
效果:
從以下可以看到只實例化了一次:
再來做一個provider實例化的時間測試:
[html]  view plain  copy
 
  1. <!DOCTYPE html>  
  2. <html lang="zh" ng-app="myApp">  
  3.   
  4. <head>  
  5.     <meta charset="UTF-8">  
  6.     <title>AngularJS學習</title>  
  7.     <script type="text/javascript" src="./1.5.3/angular.min.js"></script>  
  8. </head>  
  9.   
  10. <body>  
  11.     <div ng-controller="myCtrl1">  
  12.         <button ng-click="onclick1()">請點擊我1</button>  
  13.     </div>  
  14.     <div ng-controller="myCtrl2">  
  15.         <button ng-click="onclick2()">請點擊我2</button>  
  16.     </div>  
  17. </body>  
  18. <script type="text/javascript">  
  19. var app = angular.module('myApp', []);  
  20. app.controller('myCtrl1', function($scope) {  
  21. /*    $scope.onclick1 = function() {  
  22.         test("林炳文Evankaka");  
  23.     };*/  
  24. });  
  25. app.controller('myCtrl2', function($scope) {  
  26. /*    $scope.onclick2 = function() {  
  27.         test("我到底是誰");  
  28.     };*/  
  29. });  
  30. app.provider('test', function() {  
  31.     console.log('instance test');  
  32.     var f = function(name) {  
  33.         alert("Hello, " + name);  
  34.     };  
  35.     this.$get = function() { //一定要有!  
  36.         return f;  
  37.     };  
  38. });  
  39. /*app.config(function(testProvider) {  
  40.     testProvider('I am config');  
  41. });*/  
  42.   
  43. app.config(function($provide) {  
  44.     $provide.provider('greeting', function() {  
  45.         this.$get = function() {  
  46.             return function(name) {  
  47.                 alert("Hello," + name);  
  48.             };  
  49.         };  
  50.     });  
  51.   /*  greetingProvider('ff');*/  
  52. });  
  53. </script>  
  54.   
  55. </html>  
頁面刷新后,我們發現即使不注入這個providrer,但也它也進行實例化了,而service/factory則是第一次注入時才會初始化。而也這是為什么它可以注入到config的一個原因吧!
什么時候使用provider()方法

(1)當我們希望在應用開始前對service進行配置的時候就需要使用到provider()。比如,我們需要配置services在不同的部署環境里面(開發,演示,生產)使用不同的后端處(2)理的時候就可以使用到了
當我們打算發布開源provider()也是首選創建service的方法,這樣就可以使用配置的方式來配置services而不是將配置數據硬編碼寫到代碼里面。
 

四、Service、Factory、Provider三者區別

 
1 ) 用 Factory 就是創建一個對象,為它添加屬性,然后把這個對象返回出來。你把 service 傳進 controller 之后,在 controller 里這個對象里的屬性就可以通過 factory 使用了。
2) Service 是用"new"關鍵字實例化的。因此,你應該給"this"添加屬性,然后 service 返回"this"。你把 service 傳進 controller 之后,在controller里 "this" 上的屬性就可以通過 service 來使用了。
3) Providers 是唯一一種你可以傳進 .config() 函數的 service。當你想要在 service 對象啟用之前,先進行模塊范圍的配置,那就應該用 provider。
4)Factory/service是第一個注入時才實例化,而provider不是,它是在config之前就已實例 化好
同一函數三種不同寫法:
[html]  view plain  copy
 
  1. <!DOCTYPE html>  
  2. <html lang="zh" ng-app="myApp">  
  3. <head>  
  4.     <meta charset="UTF-8">  
  5.     <title>AngularJS學習</title>  
  6.     <script type="text/javascript" src="./1.5.3/angular.min.js"></script>  
  7. </head>  
  8. <body>  
  9.     <div ng-controller="myCtrl">  
  10.         <p>{{ output1 }}</p>  
  11.         <p>{{ output2 }}</p>  
  12.         <p>{{ output3 }}</p>  
  13.     </div>  
  14.     <div ng-controller="myCtrl2">  
  15.     </div>  
  16. </body>  
  17. <script type="text/javascript">  
  18. var app = angular.module('myApp', []);  
  19. app.controller('myCtrl', function($scope,testService, testFactory, testProvider) {  
  20.     $scope.output1 = testService.lable;  
  21.     $scope.output2 = testFactory.lable();  
  22.     $scope.output3 = testProvider;  
  23. });  
  24. app.controller('myCtrl2', function($scope,testService, testFactory, testProvider) {  
  25. });  
  26. app.service('testService',function(){  
  27.       console.log('instance testService');  
  28.      this.lable = 'this is service';  
  29. });  
  30. app.factory('testFactory', function () {  
  31.       console.log('instance testFactory');  
  32.      return{  
  33.         lable: function(){  
  34.         return 'this is factory';  
  35.         }  
  36.     };  
  37. });  
  38. app.provider('testProvider', function(){  
  39.     console.log('instance testProvider');  
  40.     this.$get = function(){  
  41.         return 'this is provider';  
  42.     };  
  43. });  
  44. </script>  
  45. </html>  


看console的輸出,可以知道都只實例 化了一次:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM