在AngularJS中,我們經常將通用的業務邏輯封裝在服務裏面,這樣一來,不僅減少了代碼量,而且使出錯率也降低了,代碼的易讀性也提高了,所以說,我們經常用到了業務邏輯,或者是說持久化數據化操作應該放在自定義的服務裏面,而不是Controller裏面。下面說一下provider、service、factory的定義方式還有主要區別
1 , factory服務
app.factory('name',function(){return obj})
name爲服務的名字,第二個參數傳入一個函數,函數需要有一個返回值obj,返回一個對象.實際被注入的服務就是這個對象.
serviceApp.factory('myConfig',function(){ var myname = 'code_bunny'; var age = 12; var id = 1; return { name: myname, age: age, getId: function(){ return id } } });
或者是這樣:
serviceApp.factory('myConfig',function(){ return new constructorFun() }); function constructorFun(){ var myname = 'code_bunny'; var age = 12; var id = 1; this.name = myname; this.age = age; this.getId = function(){ return id } }
用factory 就是創建一個對象,爲它添加屬性,然後把這個對象返回出來。
factory服務是最常見最常用的服務類型,幾乎可以滿足90%的自己開發的需求,使用它可以編寫一些邏輯,通過這些邏輯最後返回所需要的對象.比如使用$http來獲取一些數據.我們就在factory創建的服務裏抓取數據,最後返回.
它和constant,value最大的區別是,factory服務是有一個處理過程,經過這個過程,才返回結果的.
2 , service服務
app.service('name',constructor)
name爲服務的名字,constructor是一個構造函數.
js:
serviceApp.service('myConfig',function(){ var myname = 'code_bunny'; var age = 12; var id = 1; this.name = myname; this.age = age; this.getId = function(){ return id } });
或者是這樣:
serviceApp.service('myConfig',constructorFun); function constructorFun(){ var myname = 'code_bunny'; var age = 12; var id = 1; this.name = myname; this.age = age; this.getId = function(){ return id } }
service和factory的區別在於,它第二個參數傳入的是一個構造函數,最後被注入的服務是這個構造函數實例化以後的結果.所以基本上使用service創建的服務的,也都可以使用factory來創建.
所以這裏,factory服務的第二種寫法和使用service是一致的:
serviceApp.factory('myConfig',function(){ return new constructorFun() });
//等價於 serviceApp.service('myConfig',constructorFun);
3,provider服務
app.provider('name',function(){ .... return { ... $get:function(){ ... return obj } } })
name爲服務的名字,第二個參數接受一個函數,函數返回一個對象,返回的對象比如要有$get方法,$get方法必須要返回一個對象obj,這個對象就是真正被注入的服務.
栗子一:
js:
serviceApp.provider('myConfig',function(){ return { $get:function(){ var myname = 'code_bunny'; var age = 12; var id = 1; return { name: myname, age: age, getId: function(){ return id } } } } });
Providers是唯一 一種你可以傳進 .config() 函數的service。(provider,factory,service)
在provider服務裏定義的方法,可以在config函數裏調用.注意調用的格式:
serviceApp.config(function(myConfigProvider){ myConfigProvider.setID(2) });
被注入的服務名不叫myConfig,而是myConfigProvider.然後在函數裏面可以調用myConfigProvider的setID方法(也就是myConfig的setID方法).
通過這種方式,使得我們的服務可以被手動配置,比如這裏可以配置id.
ng有很多內置的服務都有這樣的功能,比如$route服務,$location服務,當我們通過$routeProvider和$locationProvider來配置的時候,其本質就是這些服務是通過provider創建的.
補充:
(1),裝飾
app.config(function($provide){ $provide.decorator('name',function($delegate){ $delegate.money = '100w'; return $delegate }) });
同樣是通過config,在參數函數中注入$provider服務,$provider服務有個decorator方法,它接受兩個參數,第一個參數'name',是要被裝飾的服務的名字,第二個參數是一個函數,函數中注入$delegate,$delegate就是被裝飾的服務的實例,然後在函數中操作$delegate,就相當於操作了該服務的實例.
注意:
1.最後一定要return $delegate,這樣服務纔算被裝飾完成了.
2.constant服務是不能被裝飾的.
(2),$watch:持續監聽數據上的變化,更新界面,(兩個controller用同一個實例對象 每個控制器都需要$watch 數據纔會更新
$scope.$watch(myConfig.love,function(){$scope.love = myConfig.love;});)
var serviceApp = angular.module('serviceApp',[]); serviceApp.controller('myCtrl',function($scope,myConfig){ $scope.name = myConfig.name; $scope.love = myConfig.love; $scope.age = myConfig.age; $scope.money = myConfig.money; $scope.id = myConfig.getId(); $scope.$watch(myConfig.love,function(){$scope.love = myConfig.love;});
})
serviceApp.controller('myOtherCtrl',function($scope,myConfig){ $scope.name = myConfig.name; $scope.love = myConfig.love; angular.extend(myConfig,{love:'zxg'}); $scope.$watch(myConfig.love,function(){$scope.love = myConfig.love;}); });
(3),constant:
app.constant('name',obj)
name爲服務的名字,obj爲一個json對象.
constant服務不能通過decorator進行裝飾
constant創建服務返回一個json對象(也就是第二個參數中傳入的對象),這個對象裏可以有參數,可以有方法,並且,屬性和方法都可以在控制器中修改,新增,但是按照它的設計本意,一般constant創建的服務不會去修改它的內容,需要修改內容,最好用value來創建服務.
(4),value服務:
app.value('name',obj)
name爲服務的名字,obj爲一個json對象.
value創建服務返回一個json對象(也就是第二個參數中傳入的對象),這個對象裏可以有參數,可以有方法,並且,屬性和方法都可以在控制器中修改,新增,按照它的設計本意,如果屬性和方法需要被修改內容,就用value來創建服務.
constant和value主要就是用於存放一些數據或方法以供使用,區別是constant一般是存放固定內容,value存放可能會被修改的內容
總結上面的內容:
1.服務的實例被注入到控制器以後,都是一個引用對象,無論被注入多少個控制器中,實際都指向同一個對象,所以,無論修改其中的哪一個,其它所有的服務都會被改變.
2.服務的實例被修改過後,ng不會自動同步,需要使用$scope.$watch()監測其變化並手動刷新視圖.
3.constant服務不能通過decorator進行裝飾.
4.一些固定的參數和方法,使用constant
5.可能被修改的參數和方法,使用value
6.通過邏輯處理後得到的參數或方法,使用factory
7.可以使用factory的也可以使用service,反之亦然(一般就是用factory)
8.可以手動配置參數的服務,使用provider