在Angular中,服務(wù)的本質(zhì)是一些和控制器捆綁在一起的可替換的對(duì)象,通過這些對(duì)象提供了在應(yīng)用的整個(gè)生命周期都存有數(shù)據(jù)的方法,當(dāng)重載或刷新頁(yè)面時(shí),數(shù)據(jù)不會(huì)被清除,而且還與加載之前保持一致。
Angular服務(wù)介紹
在Angular中服務(wù)是一種單例對(duì)象。服務(wù)主要的功能是為實(shí)現(xiàn)應(yīng)用的功能提供數(shù)據(jù)和對(duì)象。它又可以分為內(nèi)置服務(wù)和自定義服務(wù)
內(nèi)置服務(wù)
Angular提供了很多內(nèi)置服務(wù),如$scope、$http、$window、$location等。
html:
<div ng-controller="MyController">
<div>當(dāng)前的地址是: {{url}}</div>
<button ng-click="onclick()">顯示地址</button>
</div>
var myapp = angular.module('MyApp', []);
myapp.controller('MyController', ['$scope', function($scope){
$scope.onclick = function () {
$scope.url = $location.absUrl();
}
}])
$location服務(wù)除了包含absUrl()方法外,還有search()和path()等方法。同時(shí)它還提供了$locationChangeStart和$locationChangeSuccess方法
自定義服務(wù)
自定義服務(wù)有兩種方法,一是使用內(nèi)置的$provider服務(wù),另一種是調(diào)用模塊(Module)中的服務(wù)注冊(cè)方法,如factory、service、constant和value等方法
html:
<div ng-controller="myCtrl">
<div>服務(wù)返回的值:
<span>{{info('name')}}</span>
<span>{{info('sex')}}</span>
<span>{{info('score')}}</span>
</div>
</div>
javascript:
var app = angular.module('myApp', []);
app.factory('$output', function () {
var stu = {
name: '張三',
sex: '男',
score: 60
}
return stu;
});
app.controller('myCtrl', ['$scope', '$output', function ($scope, $output) {
$scope.info = function (n) {
for (_n in $output) {
if (_n == n) {
return ($output[_n]);
}
}
}
}]);
創(chuàng)建Angular服務(wù)
在Angular中創(chuàng)建自定義服務(wù),只需要先構(gòu)建一個(gè)模塊(Module),然后在構(gòu)建過程中調(diào)用內(nèi)置的$provide服務(wù),通過該服務(wù)的工廠函數(shù)來創(chuàng)建屬于自己的Angular服務(wù)。除此之外,還可以調(diào)用模塊中的factory、service、constant、value方法來創(chuàng)建。
使用factory方法自定義服務(wù)
在Angular中,最常用的創(chuàng)建自定義服務(wù)的,就是factory方法了
app.factory(name, fn);
html:
<div ng-controller="MyController">
<div>{{str('我是factory返回的內(nèi)容')}}</div>
<div>{{name(1)}}</div>
</div>
javascript:
var myapp = angular.module('MyApp', []);
myapp.factory('outfun', function () {
return {
str: function (s) {
return s;
}
}
});
myapp.factory('outarr', function () {
return ['張三', '李四', '王五'];
});
myapp.controller('MyController', function ($scope, outfun, outarr) {
$scope.str = function (n) {
return outfun.str(n);
}
$scope.name = function (n) {
return outarr[n];
}
});
使用service方法自定義服務(wù)
使用service方法也可以自定義服務(wù),與factory不同的是,它可以接受一個(gè)構(gòu)造函數(shù)
app.service(name, fn)
其中,fn為構(gòu)造函數(shù),當(dāng)注入該服務(wù)時(shí),通過該函數(shù)并使用new關(guān)鍵字來實(shí)例化服務(wù)對(duì)象
html:
<div ng-controller="MyController">
<div class="show">姓名: {{name}}</div>
<div class="show">郵件: {{email}}</div>
<div class="show">{{title}}</div>
<button ng-click="say()">主題</button>
</div>
javascript:
var myapp = angular.module('MyApp', []);
myapp.service('student', function () {
this.name = 'Kaindy',
this.email = 'kaindy7633@163.com',
this.say = function () {
return 'Hello, Angular!';
}
});
myapp.controller('MyController', ['$scope', 'student', function ($scope, student){
$scope.name = student.name;
$scope.email = student.email;
$scope.say = function () {
$scope.title = student.say();
}
}]);
使用constant和value方法自定義服務(wù)
使用constant和value方法創(chuàng)建服務(wù),常用于返回一個(gè)常量。
app.constant(name, value)
app.value(name, value)
html:
<div ng-controller="MyController">
<div class="show">圖書ISBN號(hào): {{BOOK}}</div>
<div class="show">美元兌換價(jià): {{USD}}</div>
</div>
javascript:
var myapp = angular.module('MyApp', []);
myapp.constant('$ISBN', {
BOOK: '9898733238'
});
myapp.value('$RATE', {
USD: 614.28
});
myapp.controller('MyController', function($scope, $ISBN, $RATE){
var n = 600;
angular.extend($RATE, {USD: n});
$scope.BOOK = $ISBN.BOOK;
$scope.USD = $RATE.USD;
})
管理服務(wù)的依賴
添加自定義服務(wù)依賴項(xiàng)方法
我們?cè)谧远x服務(wù)時(shí),會(huì)添加其他各類對(duì)象或服務(wù),有下面三種方式:
(1) 隱式聲明
在參數(shù)中直接調(diào)用,但這種方式在代碼壓縮時(shí)注入的對(duì)象可能會(huì)失效
app.factory('ServiceName', function(dep1, dep2) {})
(2) 調(diào)用$inject屬性
將需要注入的服務(wù)對(duì)象包裝成一個(gè)數(shù)組,作為$inject的屬性值,但這種方式效率很低
var sf = function(dep1, dep2) {};
sf.$inject = ['dep1', 'dep2'];
app.factory('ServieceName', sf);
(3) 顯式聲明
在創(chuàng)建服務(wù)的函數(shù)中,添加一個(gè)數(shù)組,在數(shù)組中按順序聲明需要注入的服務(wù)或?qū)ο竺Q,這種方式既高效也不會(huì)丟失代碼,推薦使用
app.factory('ServiceName', ['dep1', 'dep2', function(dep1, dep2) {} ])
html:
<div ng-controller="MyController">
<div class="show">你選擇的是:{{result}}</div>
<button ng-click="confirm('你真的要?jiǎng)h除這條記錄嗎?')">刪除</button>
</div>
javascript:
var myapp = angular.module('MyApp', []);
myapp.service('notify', ['$window', function ($win) {
return function (msg) {
return $win.confirm(msg) ? '確定' : '取消';
}
}]);
myapp.controller('MyController', ['$scope', 'notify', function ($scope, notify) {
$scope.confirm = function (msg) {
$scope.result = notify(msg);
}
}]);
嵌套注入服務(wù)
在Angular中,有時(shí)需要將一個(gè)自定義的服務(wù)注入到另一個(gè)自定義的服務(wù)中,形成嵌套注入的形式,通常只需要將被注入的服務(wù)作為內(nèi)置服務(wù),采用顯式聲明的方式注入即可
html:
<div ng-controller="MyController">
<button ng-click="ask(false, '你輸入的內(nèi)容不正確')">提示框</button>
<button ng-click="ask(true, '你真的要?jiǎng)h除這條記錄嗎?')">詢問框</button>
</div>
javascript:
var myapp = angular.module('MyApp', []);
// 使用factory定義confirm服務(wù)
myapp.factory('confirm', ['$window', function ($win) {
return function (msg) {
$win.confirm(msg);
}
}]);
// 將confirm服務(wù)顯式的注入到notify服務(wù)中
myapp.service('notify', ['$window', 'confirm', function ($win, con) {
return function (t, msg) {
return (t) ? con(msg) : $win.alert(msg);
}
}]);
myapp.controller('MyController', ['$scope', 'notify', function ($scope, notify) {
$scope.ask = function (t, msg) {
notify(t, msg);
}
}])
添加服務(wù)的其他設(shè)置
創(chuàng)建好的服務(wù)一般比較復(fù)雜,如果后期需要修改,往往面臨很高的風(fēng)險(xiǎn),Angular為服務(wù)添加了一些設(shè)置項(xiàng),如裝飾器(decorator),可以在不修改原代碼的情況下為服務(wù)添加其他功能
服務(wù)的裝飾器
裝飾器(decorator)是Angular中內(nèi)置服務(wù)$provide所特有的一項(xiàng)設(shè)置函數(shù),通過它可以攔截服務(wù)在實(shí)例化時(shí)創(chuàng)建的一些功能,并對(duì)原有功能進(jìn)行優(yōu)化和替代。
$provide.decorator('ServiceName', Fn)
-
$provide表示注入后創(chuàng)建的服務(wù)對(duì)象 -
ServiceName表示需要攔截的服務(wù)名稱 -
Fn表示服務(wù)在實(shí)例化時(shí)調(diào)用的函數(shù),該函數(shù)在執(zhí)行時(shí)需要添加一個(gè)名為$delegate的參數(shù),該參數(shù)代表服務(wù)實(shí)例化后的對(duì)象,服務(wù)的新功能就是通過這個(gè)對(duì)象進(jìn)行擴(kuò)展和優(yōu)化的
示例代碼:
<div ng-controller="MyController">
<div class="show">姓名: {{stu.name}}</div>
<div class="show">郵件: {{stu.email}}</div>
<div class="show">主題: {{stu.title}}</div>
</div>
var myapp = angular.module('MyApp', []);
// 使用工廠函數(shù)factory定義student服務(wù)
myapp.factory('student', function () {
return {
name: 'Kaindy',
email: 'kaindy7633@gmail.com'
}
});
// 使用$provider的裝飾器decorator為服務(wù)student擴(kuò)展一個(gè)title屬性
myapp.config(function ($provide) {
$provide.decorator('student', function ($delegate) {
$delegate.title = 'Hello, Angular!';
return $delegate;
})
});
myapp.controller('MyController', function ($scope, student) {
$scope.stu = student;
});