本教程使用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来操作数据、定义函数。

  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(内联注解,推荐使用):

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

方式2($inject注解):

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

方式3(隐式注解,不推荐使用):

  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使用实例

一个完整实例:

  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. app.service('myService', function() {
  29. console.log('instance myService');
  30. var privateValue = "I am Private";
  31. this.variable = "This is public";
  32. this.getPrivate = function() {
  33. return privateValue;
  34. };
  35. });
  36. </script>
  37. </html>

效果如下:

另外,从这里可以看到两个controller注入同一个service,但是最终只实例化了一次!
 
注意:seivce定义的服务不能在.config中使用!只有provider定义的才可以
 

二、Factory使用详解

Factory 一般就是创建一个对象,然后在对这个对象添加方法与数据,最后将些对象返回即可。然后注入到Controller层中即可。
 
使用实例:
  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. app.factory('myFactory', function() {
  29. console.log('instance myFactory');
  30. var factory = {};
  31. var privateValue = "I am Private";
  32. factory.variable = "This is public";
  33. factory.getPrivate = function() {
  34. return privateValue;
  35. };
  36. return factory;
  37. });
  38. </script>
  39. </html>

效果:

从下面可以看到只实例化了一次,两下Controller注入同一个factory,但是最终只实例化了一次!
记得一定要return一个Object对象,否则会报如下错误:
 
AngularJS中的Services:

三、provider使用详解

    $provide服务负责告诉Angular如何创造一个新的可注入的东西:即服务。服务会被叫做供应商的东西来定义,你可以使用$provide来创建一个供应商。你需要使用$provide中的provider()方法来定义一个供应商,同时你也可以通过要求$provide被注入到一个应用的config函数中来获得$provide服务。使用方法是返回一个$get函数,注意在config阶段,只有provider能被注入。其它用法和service一样。
下面是一个实例。
  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. app.provider('testProvider', function(){
  29. console.log('instance testProvider');
  30. var f = function(name) {
  31. alert("Hello, " + name);
  32. };
  33. this.$get = function(){ //一定要有!
  34. return f;
  35. };
  36. });
  37. </script>
  38. </html>

效果:

从以下可以看到只实例化了一次:

再来做一个provider实例化的时间测试:

  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) {
  19. /*    $scope.onclick1 = function() {
  20. test("林炳文Evankaka");
  21. };*/
  22. });
  23. app.controller('myCtrl2', function($scope) {
  24. /*    $scope.onclick2 = function() {
  25. test("我到底是谁");
  26. };*/
  27. });
  28. app.provider('test', function() {
  29. console.log('instance test');
  30. var f = function(name) {
  31. alert("Hello, " + name);
  32. };
  33. this.$get = function() { //一定要有!
  34. return f;
  35. };
  36. });
  37. /*app.config(function(testProvider) {
  38. testProvider('I am config');
  39. });*/
  40. app.config(function($provide) {
  41. $provide.provider('greeting', function() {
  42. this.$get = function() {
  43. return function(name) {
  44. alert("Hello," + name);
  45. };
  46. };
  47. });
  48. /*  greetingProvider('ff');*/
  49. });
  50. </script>
  51. </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之前就已实例 化好
同一函数三种不同写法:
  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的输出,可以知道都只实例 化了一次:

angular.js的依赖注入解析的更多相关文章

  1. Angular JS的依赖注入

    依赖注入是一个在组件中给出的替代了硬的组件内的编码它们的依赖关系的软件设计模式.这减轻一个组成部分,从定位的依赖,依赖配置.这有助于使组件可重用,维护和测试. AngularJS提供了一个至高无上的依 ...

  2. angular中自定义依赖注入的方法和decorator修饰

    自定义依赖注入的方法 1.factory('name',function () { return function(){ } }); 2.provider('name',function(){ thi ...

  3. angular路由 模块 依赖注入

    1.模块 var helloModule=angular.module('helloAngular',[]); helloModule.controller('helloNgCrtl',['$scop ...

  4. js 实现依赖注入的思想,后端框架思想搬到前端来

    前述:咱们写一些页面的时候,很多需要用ajax来实现,显示又有很多表单提交的add或者update操作,太烦了,能不能有什么方法能够简单些呢? 说实话我都是被公司给逼的 应用场景: 前后端一一对应.表 ...

  5. angular.js使用ui-router注入报错,这里是版本问题导致的

    报错如下: common.ts:604Uncaught SyntaxError: Unexpected token ) stateEvents.ts:211Uncaught SyntaxError: ...

  6. angular 工厂模式依赖注入

    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; ...

  7. angular 服务之间依赖注入

    import { Injectable } from '@angular/core'; @Injectable() export class LoggerServiceService { constr ...

  8. angular 第二种依赖注入

    import { Injectable } from '@angular/core'; import { ProductServiceService, Product } from './produc ...

  9. 理论+案例,带你掌握Angular依赖注入模式的应用

    摘要:介绍了Angular中依赖注入是如何查找依赖,如何配置提供商,如何用限定和过滤作用的装饰器拿到想要的实例,进一步通过N个案例分析如何结合依赖注入的知识点来解决开发编程中会遇到的问题. 本文分享自 ...

随机推荐

  1. java读取配置文件的方法

    1. Preferences类 这个主要是设置个人喜好.它的数据一般存在系统目录或是用户目录.还可以操作注册表. 2. Properties类 保存键值对.可以指定路径. 3. commons con ...

  2. 13.8.8 div块 居中

    <div style="border:1px solid blue;width:760px; height:410px; position:absolute; left:50%; to ...

  3. 在jsp中怎么使用Cookie?el表达式中获取cookie的问题

    初学jsp,不清楚cookie的使用方法,希望高手指点一下!   一般来说有两种办法,在JSP中使用Java的嵌入脚本. 例如: 写入Cookie <html> <head>. ...

  4. ArcGIS Desktop Python add-ins 共享和安装插件

    1)   共享和安装插件 共享Python插件的关键是.esriaddin文件;为了获取该插件功能,其他用户只要在本机执行安装操作或通过网络引用该插件就可以. ArcGIS插件安装工具 当用户双击一个 ...

  5. EditPlus常用快捷键[私人]

    EditPlus快捷键大全网上一搜一大把, 本文档只记录自己常用的快捷键, 随时更新: 必用: ctrl + c 复制 ctrl + x 剪切 ctrl + v 粘贴 ctrl + z 回滚 ctrl ...

  6. SSH中设置字符编码防止乱码

    1.在web.xml中加入一个过滤器和过滤范围的配置 <filter><filter-name>encoding</filter-name><filter-c ...

  7. Android RelativeLayout属性介绍

    在Android开发当中,虽然有五大布局,但我推荐使用的是相对布局,Google也是推荐使用相对布局,所有对RelativeLayout布局,常用的属性做一个整理: android:layout_ma ...

  8. Python学习-16.Python中的错误处理

    虽然叫错误,但跟 C# 中的异常是一回事.只不过 Python 中叫错误(Error)而 C# 中叫异常(Exception). 先手工产生一个异常: file = open('','r') 上面一句 ...

  9. ABP 基础设施层——集成 Entity Framework

    本文翻译自ABP的官方教程<EntityFramework Integration>,地址为:http://aspnetboilerplate.com/Pages/Documents/En ...

  10. 在TFS持续集成(持续发布)中执行Telnet任务

    Telnet是一种在因特网或局域网上使用虚拟终端连接,提供双向交互式文本通信设备的协议. 它是最早的互联网通讯协议之一.自1969年启用以来,已经经过了将近50年时间,在开放式的操作系统中拥有广泛的用 ...