Angular的服务
Angular服务介绍
介绍
Angular服务是一种单例对象。所谓单例,指的是服务在每一个应用中只会被实例化一次,并且是在需要时异步进行加载。服务的主要功能是为了实现应用的功能提供数据和对象。控制器中原有的数据在不需要时都将被Angular清除,在需要的时候重新被实例化。服务就在一定程度上解决了这个问题。它本身是和控制器捆绑在一起的可替换的对象,通过这些对象提供了在应用的整个生命周期都存有的数据方法。当重载或者刷新页面时,数据不会被清除,而且还与加载之前保持一致。
内置服务
$scope
$http
$window
$location
$rootScope
这些服务的详细使用方法,可以参考Angular的官方API
自定义服务
内置$provider服务
代码举例
<!DOCTYPE html> <html lang="zh_CN"> <head> <meta charset="UTF-8"> <title>Angular基础</title> </head> <body> <div ng-app="myApp"> <div ng-controller="firstCtrl"> <span>{{info('name')}}</span> <span>{{info('age')}}</span> <span>{{info('sex')}}</span> </div> </div> <script src="components/angular/angular.min.js"></script> <script type="application/javascript"> var myApp = angular.module('myApp', [], function ($provide) { //$provide.provider $provide.provider('providerService01', function () { this.$get = function () { return { message: 'this is providerService01' }; } }); // $provide.factory $provide.factory('factoryService01', function () { var stu = { name: 'zs', age: '12', sex: 'man' }; return stu; }); // $provide.service $provide.service('serviceService01', function () { return { message: 'this is serviceService01' }; }); }); myApp.controller('firstCtrl', ['$scope', 'providerService01', 'factoryService01', function ( $scope, providerService01, factoryService01) { console.log(providerService01); console.log(factoryService01); $scope.name = "张三"; $scope.info = function (n) { for (_n in factoryService01) { if (_n == n) { return (factoryService01[_n]); } } } } ]); </script> </body> </html>
解析代码
内置服务和自定义 服务都是通过依赖注入方式向控制器添加服务。服务被注入的动作实际上是Angular编译器引入实例化对象的过程。所以当通过依赖注入的方式向控制器添加自定义服务时,这个服务已经是一个实例化后的服务对象。
使用config方法引入
代码举例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="components/angular/angular.min.js"></script> </head> <body> <div ng-app="a6_2_2"> <div ng-controller="c6_2_2"> {{name}} </div> </div> <script type="application/javascript"> var myApp = angular.module('a6_2_2', []) .config(['$provide', function ($provide) { $provide.provider('providerService', function () { this.$get = function () { return { message: 'this is providerService01' }; } }); $provide.provider('providerService02', function () { this.$get = function () { var _name = ""; var service = {}; service.setName = function (name) { _name = name; } service.getName = function () { return _name; } return service; } }); }]) myApp.controller('c6_2_2', ['$scope', 'providerService', function ($scope, providerService) { console.log(providerService); providerService02.setName("服务二"); $scope.name = providerService02.getName(); }]); </script> </body> </html>
创建Angular服务
调用模块中的服务注册方法,如factory, service,constant和value等方法。
factory
- 代码举例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="components/angular/angular.min.js"></script> </head> <body> <div ng-app="a6_3"> <div ng-controller="c6_3"> <span>{{str('123')}}</span> <span>{{number(1)}}</span> </div> </div> <script type="application/javascript"> var myApp = angular.module('a6_3', []); myApp.factory('$outfun',function(){ return { str : function(s){ return s; } } }); myApp.factory('$outarra',function(){ return ['1','2','3','4']; }); myApp.controller('c6_3',['$scope','$outfun','$outarra',function($scope,$outfun,$outarra){ $scope.str = function(s){ return $outfun.str(s); } $scope.number = function(n){return $outarra[n]} }]) </script> </body> </html>
- 源码解析
app.factory(name,function),name是创建服务的名称,fn表示服务实现的功能函数,可以返回一个能被注入对象的数组或者函数,该函数在服务实例化时被调用。
service
- 代码举例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="components/angular/angular.min.js"></script> </head> <body> <div ng-app="a6_4"> <div ng-controller="c6_4"> <span>{{name}}</span> <span>{{age}}</span> <span>{{title}}</span> </div> </div> <script type="application/javascript"> var myApp = angular.module('a6_4', []); myApp.service('$outSer',function(){ this.name = '张三'; this.age = '100'; this.say = function(){ return 'hello world!'; } }) myApp.controller('c6_4',['$scope','$outSer',function($scope,$outSer){ $scope.name = $outSer.name; $scope.age = $outSer.age; $scope.say = function(){ $scope.title = $outSer.say(); } $scope.say(); }]) </script> </body> </html>
- 代码解析
如果说factory是一个对象,那么service就是被new factory 出来的一个实例化出来的一个对象。使用service方法可以返回构造函数,所以我们可以通过this方式添加两个属性和一个方法,用于注入时的回调。
在注入的过程中,通过angular检测到是service创建的服务,会自动通过关键字new实例化这个服务。
constant && value
- 代码举例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="components/angular/angular.min.js"></script> </head> <body> <div ng-app="a6_5"> <div ng-controller="c6_5"> <span>{{num1}}</span> <span>{{num2}}</span> </div> </div> <script type="application/javascript"> var myApp = angular.module('a6_5', []); myApp.constant('$cons',{num1 : '1'}) .value('$value',{num2 : '2'}); myApp.controller('c6_5',['$scope','$cons','$value',function($scope,$cons,$value){ $scope.num1 = $cons.num1; $scope.num2 = $value.num2; }]) </script> </body> </html>
- 源码解析
因为这两个服务返回的都是常量,因此控制器在注入两个服务后,同样也是实例化成一个服务对象,以对象属性的方式获取常量值。在控制器中我们还可以使用
angular.extend
方法对服务对象中的常量值进行更改,当它们两个是有区别的,最大的区别是使用constant方法创建服务返回的常量可以被注入配置函数(config)中,而使用value方法创建服务返回的值则不能注入。所以,constant方法常用于创建配置数据,而value方法则常用于创建对象和函数。
管理Angular服务的依赖
添加自定义服务依赖项方法
- 隐式指明
app.factory('serviceName',function(dep1,dep2){})
- 调用$inject属性
var sf = function(dep1,dep2){}; sf.$inject = ['dep1','dep2']; app.factory('ServiceName',sf);
- 显式声明
app.factory('ServiceName',['dep1','dep2',function(dep1,dep2){}])
嵌套注入服务
- 代码举例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="components/angular/angular.min.js"></script> </head> <body> <div ng-app="a6_6"> <div ng-controller="c6_6"> <!-- <span>{{}}</span> <span>{{}}</span> --> <button ng-click="ask(false,'您输入的内容不正确')">提示框</button> <button ng-click="ask(true,'您确定要删除吗?')">询问框</button> </div> </div> <script type="application/javascript"> var myApp = angular.module('a6_6', []); myApp.factory('$confirm',['$window',function($window){ return function(msg){ $window.confirm(msg); } }]); myApp.service('$notify',['$confirm','$window',function($confirm,$window){ return function(t,msg){ return (t) ? $confirm(msg):$window.alert(msg); } }]); myApp.controller('c6_6',['$scope','$notify',function($scope,$notify){ $scope.ask = function(t,msg){ $notify(t,msg) } }]); </script> </body> </html>
- 源码解析
service 服务中调用了 factory服务。
添加服务的其他设置
服务的装饰器
- 介绍
服务就是一项数据请求和处理的集合,在后续开发中要修改,相对来说比较困难,特别是一些内置服务。
装饰器通过她可以在不修改原有代码的情况下,添加一些其他功能。装饰器,是Angular中内置服务provider所特有的一项设置函数。
$provider.decorator('Servicename',function)
在上面的代码中,$表示注入后的创建服务对象;表示将要拦截的服务名称;表示服务在实例化时调用的函数,在执行该函数时,需要添加一个名为provider表示注入后的创建服务对象;ServiceName表示将要拦截的服务名称;fn表示服务在实例化时调用的函数,在执行该函数时,需要添加一个名为
$delegate
的参数,该参数代表实例化后的对象,通常写在配置块中。- 代码举例
.factory('$factoryService',function(){ return { name:'123' } }) .config(['$provide',function($provide){ $provide.decorator('$factoryService',function($delegate){ $delegate.title = 'hello world'; return $delegate; }) }])
服务的多例性
- 介绍
虽然服务返回的都是一个单例的对象,但是这个不代表服务并不能返回多例的对象。