出于内存占用和性能的考虑,控制器只会在需要时被实例化,并且不再需要就会被销毁。这意味着每次切换路由或重新加载视图时,当前的控制器会被AngularJS清除掉。
服务提供了一种能在应用的整个生命周期内保持数据的方法,它能够在控制器之间进行通信,并且能保证数据的一致性。当重载或者刷新界面时,数据不会被清除,而且还与加载之前保持一致。主要功能:为实现应用的功能提供数据和对象。对外提供某个特定的功能,如消息服务,文件压缩服务等,是一个独立的模块。
Angular services are singletons objects or functions that carry out
specific tasks common to web apps.
服务是一个单例对象,在每个应用中只会被实例化一次(被 $injector 实例化) ,并且是延迟加载的(需要时才会被创建) 。服务提供了把与特定功能相关联的方法集中在一起的接口。
使用服务是控制器共享数据的典型方法。
AngularJS系统内置的服务以$开头,我们也可以自己定义一个服务。
在AngularJS应用中, factory() 方法是用来注册服务的最常规方式,同时还有其他一些API可以在特定情况下帮助我们减少代码量。共有5种方法用来创建服务:
factory():在定义服务时, 第二个参数 可以接受一个包含可被注入对象的数组或函数。
第二个参数可以返回简单类型、函数乃至对象等任意类型的数据(同 value() 函数类似) 。
service():可以注册一个支持构造函数的服务,它允许我们为服务对象注册一个构造函数。
constant():可以将一个已经存在的变量值注册为服务,并将其注入到应用的其他部分当中。例如,假设我们需要给后端服务一个 apiKey ,可以用 constant() 将其当作常量保存下来。
value():如果服务的 $get 方法返回的是一个常量,那就没要必要定义一个包含复杂功能的完整服务,可以通过 value() 函数方便地注册服务。
provider():所有服务工厂都是由 provide服务创建的, provide服务负责在运行时初始化这些提供者。提供者是一个具有 get() 方法的对象, injector 通过调用 get 方法创建服务实例。provider 提供了数个不同的API用于创建服务,每个方法都有各自的特殊用途。所有创建服务的方法都构建在 provider 方法之上。provider() 方法负责在 providerCache中注册服务。
从技术上说,当我们假定传入的函数就是 get() 时, factory() 函数就是用 provider() 方法注册服务的简略形式。
第二个参数 aProvider (对象/函数/数组)aProvider 可以是多种形式。
如果 aProvider 是函数,那么它会通过依赖注入被调用,并且负责通过 get 方法返回一个对象。
如果 aProvider 是数组,会被当做一个带有行内依赖注入声明的函数来处理。数组的最后一个元素应该是函数,可以返回一个带有 get 方法的对象。
如果 aProvider 是对象,它应该带有 get 方法。
用这个方法创建服务,必须返回一个定义有 $get() 函数的对象,否则会导致错误。
自定义服务的方法一:
1、定义module ,
2、module中注入provide,或者module 的 config 方法中注入 provide(如果希望在 config() 函数中可以对服务进行配置,必须用 provider() 来定义服务。)
3、然后再调用provider方法、service方法或factory方法
<!doctype html>
<html ng-app="a6_2">
<head>
<title>使用$provide自定义服务</title>
<script src="../Script/angular.min.js"
type="text/javascript"></script>
<style type="text/css">
body {
font-size: 12px;
}
.show {
background-color: #ccc;
padding: 8px;
width: 260px;
margin: 10px 0px;
}
</style>
</head>
<body>
<div ng-controller="c6_2">
<div class="show">
服务返回的值:
<span>{{info('name')}}</span>
<span>{{info('sex')}}</span>
<span>{{info('score')}}</span>
</div>
</div>
<script type="text/javascript">
/*============服务的使用方法1=====定义module , module中注入$provide,参考本例================================*/
/*===========服务的使用方法2======module 的 config 方法中也可注入 $provide===============================*/
/*===========服务的使用方法3======module 的 provider、service、factory 方法 ==============================*/
angular.module('a6_2', [], function ($provide) {/*内置服务$provide*/
/*第一种方式:使用provide的factory自定义服务*/
// $provide.factory('$output', function () {/*调用factory方法*/
// var stu = {
// name: '张三',
// sex: '男',
// score: '60'
// };
// return stu;
// })
/*第二种方式:使用provide的provider自定义服务*/
// $provide.provider('$output', function () {/*调用provider方法*/
// this.$get = function () {//必须带this和$get
// var stu = {
// name: '张三',
// sex: '男',
// score: '60'
// };
// return stu;
// }
// })
/*第三种方式:使用provide的service自定义服务*/
$provide.service('$output', function () {/*调用service方法*/
/*写法一*/
this.name = '张三';
this.sex = '男';
this.score = '60';
/*写法二*/
// var stu = {
// name: '张三',
// sex: '男',
// score: '60'
// };
// return stu;
})
})
.controller('c6_2', function ($scope, $output) {
$scope.info = function (n) {
for (_n in $output) {/*JavaScript for...in 语句循环遍历对象的属性。*/
if (_n == n) {/*对象的键*/
return ($output[_n]);
/*通过对象的键获取对象的值*/
}
}
}
});
</script>
</body>
</html>
服务的自定义方法二:
1、创建module
2、module 直接调用 provider、service、factory 方法
<!doctype html>
<html ng-app="a6_4">
<head>
<title>使用service方法自定义服务</title>
<script src="../Script/angular.min.js"
type="text/javascript"></script>
<style type="text/css">
body {
font-size: 12px;
}
.show {
background-color: #ccc;
padding: 8px;
width: 260px;
margin: 10px 0px;
}
</style>
</head>
<body>
<div ng-controller="c6_4">
<div class="show">姓名:{{name1}}</div>
<div class="show">邮件:{{email1}}</div>
<div class="show">{{title1}}</div>
<button ng-click="say1()">主题</button>
<div class="show">姓名:{{name2}}</div>
<div class="show">邮件:{{email2}}</div>
<div class="show">{{title2}}</div>
<button ng-click="say2()">主题</button>
<div class="show">姓名:{{name3}}</div>
<div class="show">邮件:{{email3}}</div>
<div class="show">{{title3}}</div>
<button ng-click="say3()">主题</button>
<div class="show">姓名:{{name4}}</div>
<div class="show">邮件:{{email4}}</div>
<div class="show">{{title4}}</div>
<button ng-click="say4()">主题</button>
</div>
<script type="text/javascript">
angular.module('a6_4', [])
/*以下三种方法一样的效果*/
//方法一:service服务:构造器
/*使用 service() 可以注册一个支持构造函数的服务,
它允许我们为服务对象注册一个构造函数。*/
.service('$student1', function () {
/*写法一*/
// this.name = "陶国荣";
// this.email = "tao_guo_rong@163.com";
// this.say = function () {
// return "hello,angular1!";
// }
/*写法二*/
return {
name: "11111111111111",
email: "tao_guo_rong@163.com",
say: function () {
return "hello,angular1!";
}
}
})
//方法二:factory服务:
.factory("$student2", function () {
return {
/*必须返回*/
name: "22222222222",
email: "tao_guo_rong@163.com",
say: function () {
return "hello,angular2!";
}
}
})
//方法三:factory服务:构造器与服务
.factory("$student3", function () {
return new student();
/*实例化自定义函数,并返回*/
})
//方法四:provider服务
.provider("$student4", function () {
this.$get = function () {/*必须带this.$get*/
return {
/*必须返回*/
name: "44444444444",
email: "tao_guo_rong@163.com",
say: function () {
return "hello,angular4!";
}
}
}
})
.controller('c6_4', function ($scope, $student1, $student2, $student3, $student4) {
$scope.name1 = $student1.name;
$scope.email1 = $student1.email;
$scope.say1 = function () {
$scope.title1 = $student1.say();
}
$scope.name2 = $student2.name;
$scope.email2 = $student2.email;
$scope.say2 = function () {
$scope.title2 = $student2.say();
}
$scope.name3 = $student3.name;
$scope.email3 = $student3.email;
$scope.say3 = function () {
$scope.title3 = $student3.say();
}
$scope.name4 = $student4.name;
$scope.email4 = $student4.email;
$scope.say4 = function () {
$scope.title4 = $student4.say();
}
});
function student() {/*创建自定义函数*/
this.name = "33333333333";
this.email = "tao_guo_rong@163.com";
this.say = function () {
return "hello,angular3!";
}
}
</script>
</body>
</html>
常量的定义:
<!doctype html>
<html ng-app="a6_5">
<head>
<title>使用constant和value方法自定义服务</title>
<script src="../Script/angular.min.js"
type="text/javascript"></script>
<style type="text/css">
body {
font-size: 12px;
}
.show {
background-color: #ccc;
padding: 8px;
width: 260px;
margin: 10px 0px;
}
</style>
</head>
<body>
<div ng-controller="c6_5">
<div class="show">图书ISBN号:{{BOOK}}</div>
<div class="show">美元兑换价:{{USD}}</div>
<!--
结果:
图书ISBN号:978745432345
美元兑换价:600-->
</div>
<script type="text/javascript">
angular.module('a6_5', [])
.constant('$ISBN', {
BOOK: "978745432345"
})
.value('$RATE', {
USD: 614.28
})
.controller('c6_5', function ($scope, $ISBN, $RATE) {
var n = 600;
angular.extend($RATE, { USD: n });//重置后,USD为600,显示也为600
$scope.BOOK = $ISBN.BOOK;
$scope.USD = $RATE.USD;
});
</script>
</body>
</html>
何时使用 value() 和 constant()
value() 方法和 constant() 方法之间最主要的区别是, 常量constant可以注入到配置函数中, 而值value不行。
通常情况下,可以通过 value() 来注册服务对象或函数,用 constant() 来配置数据。
angular.module('myApp', [])
.constant('apiKey', '123123123')
.config(function(apiKey) {
// 在这里apiKey将被赋值为123123123
// 就像上面设置的那样
})
.value('FBid','231231231')
.config(function(FBid) {
// 这将抛出一个错误,未知的provider: FBid
// 因为在config函数内部无法访问这个值
});
参考:
《angularjs 实战》