一.constant服務(wù):
app.constant("name",obj)
name為服務(wù)的名字,obj為一個json對象.
js:
serviceApp.constant("myConfig",{?
? name:"code_bunny",? ? age:12,? ? getId:function(){return1?
? }});
二.value服務(wù):
app.value("name",obj)
name為服務(wù)的名字,obj為一個json對象.
js:
serviceApp.value("myConfig",{? ? name:"code_bunny",? ? age:12,? ? getId:function(){return1? ? }});
serviceApp.config(function($provide){
$provide.decorator("myConfig",function($delegate){
$delegate.money = "100w";return$delegate? ? })});
說明:
value創(chuàng)建服務(wù)返回一個json對象(也就是第二個參數(shù)中傳入的對象),這個對象里可以有參數(shù),可以有方法,并且,屬性和方法都可以在控制器中修改,新增,按照它的設(shè)計本意,如果屬性和方法需要被修改內(nèi)容,就用value來創(chuàng)建服務(wù).
constant和value主要就是用于存放一些數(shù)據(jù)或方法以供使用,區(qū)別是constant一般是存放固定內(nèi)容,value存放可能會被修改的內(nèi)容
注意點:
1.同constant注意點1
2.同constant注意點2
3.value可以被裝飾,所以這里myConfig服務(wù)擁有了money屬性.(裝飾具體怎么用,下面會說)
三.factory服務(wù)
app.factory("name",function(){returnobj})
name為服務(wù)的名字,第二個參數(shù)傳入一個函數(shù),函數(shù)需要有一個返回值obj,返回一個對象.實際被注入的服務(wù)就是這個對象.
js:
serviceApp.factory("myConfig",function(){varmyname
= "code_bunny";varage = 12;varid = 1;return{? ?
? ? name: myname,
age: age,? ? ? ? getId:function(){returnid? ? ? ? }? ? }});
或者是這樣:
serviceApp.factory("myConfig",function(){returnnewconstructorFun()});functionconstructorFun(){varmyname
= "code_bunny";varage = 12;varid = 1;this.name = myname;this.age =
age;this.getId =function(){returnid? ? }}
裝飾部分代碼:
serviceApp.config(function($provide){
$provide.decorator("myConfig",function($delegate){
console.log($delegate);? ? ? ? $delegate.money = "100w";return$delegate
})});
運行結(jié)果:
說明:
factory服務(wù)是最常見最常用的服務(wù)類型,幾乎可以滿足90%的自己開發(fā)的需求,使用它可以編寫一些邏輯,通過這些邏輯最后返回所需要的對象.比如使用$http來獲取一些數(shù)據(jù).我們就在factory創(chuàng)建的服務(wù)里抓取數(shù)據(jù),最后返回.
它和constant,value最大的區(qū)別是,factory服務(wù)是有一個處理過程,經(jīng)過這個過程,才返回結(jié)果的.
注意點:
1.同constant注意點1
2.同constant注意點2
3.factory返回的服務(wù)也可以被裝飾,所以這里myConfig服務(wù)擁有了money屬性.(裝飾具體怎么用,下面會說)
四.service服務(wù)
app.service("name",constructor)
name為服務(wù)的名字,constructor是一個構(gòu)造函數(shù).
js:
serviceApp.service("myConfig",function(){varmyname
= "code_bunny";varage = 12;varid = 1;this.name = myname;this.age =
age;this.getId =function(){returnid? ? }});
或者是這樣:
serviceApp.service("myConfig",constructorFun);functionconstructorFun(){varmyname
= "code_bunny";varage = 12;varid = 1;this.name = myname;this.age =
age;this.getId =function(){returnid? ? }}
裝飾部分代碼同上.
運行結(jié)果:
http://jsfiddle.net/1qj8m5ot/
http://jsfiddle.net/0bh67cog/
說明:
service和factory的區(qū)別在于,它第二個參數(shù)傳入的是一個構(gòu)造函數(shù),最后被注入的服務(wù)是這個構(gòu)造函數(shù)實例化以后的結(jié)果.所以基本上使用service創(chuàng)建的服務(wù)的,也都可以使用factory來創(chuàng)建.
所以這里,factory服務(wù)的第二種寫法和使用service是一致的:
serviceApp.factory("myConfig",function(){returnnewconstructorFun()});//等價于serviceApp.service("myConfig",constructorFun);
注意點:
1.同constant注意點1
2.同constant注意點2
3.service返回的服務(wù)也可以被裝飾,所以這里myConfig服務(wù)擁有了money屬性.(裝飾具體怎么用,下面會說)
五.provider服務(wù)
app.provider("name",function(){ ....return{ ... $get:function(){ ...returnobj}? ?? }})
name為服務(wù)的名字,第二個參數(shù)接受一個函數(shù),函數(shù)返回一個對象,返回的對象比如要有$get方法,$get方法必須要返回一個對象obj,這個對象就是真正被注入的服務(wù).
栗子一:
js:
serviceApp.provider("myConfig",function(){return{
$get:function(){varmyname = "code_bunny";varage = 12;varid =
1;return{? ? ? ? ? ? ?? name: myname,? ? ? ? ? ? ?? age: age,
getId:function(){returnid? ? ? ? ? ? ?? }? ? ? ? ?? }? ? ?? }?? }});
裝飾部分代碼同上.
運行結(jié)果:?http://jsfiddle.net/2pz2ft73/
說明:
provider服務(wù)的第二個參數(shù)的返回值中必須要有$get方法(除了$get,還可以有其它方法,后面的例子會說到),$get方法就相當于factory服務(wù)的第二個參數(shù),最后要返回一個對象,這個對象就是真正被注入的服務(wù):
栗子二:
js:
serviceApp.provider("myConfig",function(){varid
= 1;return{? ? ? ? setID:function(newID){? ? ? ? ? ? id = newID
},? ? ? ? $get:function(){varmyname = "code_bunny";varage = 12;return{
name: myname,? ? ? ? ? ? ? ? age: age,
getId:function(){returnid? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }
}});serviceApp.config(function(myConfigProvider){
myConfigProvider.setID(2)});
裝飾部分代碼同上.
運行結(jié)果:http://jsfiddle.net/hcpemex3/
說明:
這里的provider服務(wù)不僅僅返回了$get方法,還返回了setID方法,然后id變量是寫在函數(shù)里的,返回值的外面,形成一個閉包,可以被修改.
然后,在provider服務(wù)里定義的方法,可以在config函數(shù)里調(diào)用.注意調(diào)用的格式:
serviceApp.config(function(myConfigProvider){? ? myConfigProvider.setID(2)});
被注入的服務(wù)名不叫myConfig,而是myConfigProvider.然后在函數(shù)里面可以調(diào)用myConfigProvider的setID方法(也就是myConfig的setID方法).
通過這種方式,使得我們的服務(wù)可以被手動配置,比如這里可以配置id.
ng有很多內(nèi)置的服務(wù)都有這樣的功能,比如$route服務(wù),$location服務(wù),當我們通過$routeProvider和$locationProvider來配置的時候,其本質(zhì)就是這些服務(wù)是通過provider創(chuàng)建的.
注意點:
1.同constant注意點1
2.同constant注意點2
3.provider返回的服務(wù)也可以被裝飾,所以這里myConfig服務(wù)擁有了money屬性.(裝飾具體怎么用,下面會說);
六.裝飾服務(wù)
其實通過上面這么多的例子,看也能看懂裝飾是什么了...
app.config(function($provide){$provide.decorator("name",function($delegate){
$delegate.money = "100w";return$delegate})});
同樣是通過config,在參數(shù)函數(shù)中注入$provider服務(wù),$provider服務(wù)有個decorator方法,它接受兩個參數(shù),第一個參數(shù)"name",是要被裝飾的服務(wù)的名字,第二個參數(shù)是一個函數(shù),函數(shù)中注入$delegate,$delegate就是被裝飾的服務(wù)的實例,然后在函數(shù)中操作$delegate,就相當于操作了該服務(wù)的實例.
注意:
1.最后一定要return $delegate,這樣服務(wù)才算被裝飾完成了.
2.constant服務(wù)是不能被裝飾的.
栗子就不說了吧,上面的都是~
總結(jié)上面的內(nèi)容:
1.服務(wù)的實例被注入到控制器以后,都是一個引用對象,無論被注入多少個控制器中,實際都指向同一個對象,所以,無論修改其中的哪一個,其它所有的服務(wù)都會被改變.
2.服務(wù)的實例被修改過后,ng不會自動同步,需要使用$scope.$watch()監(jiān)測其變化并手動刷新視圖.
3.constant服務(wù)不能通過decorator進行裝飾.
4.一些固定的參數(shù)和方法,使用constant
5.可能被修改的參數(shù)和方法,使用value
6.通過邏輯處理后得到的參數(shù)或方法,使用factory
7.可以使用factory的也可以使用service,反之亦然(一般就是用factory)
8.可以手動配置參數(shù)的服務(wù),使用provider
七.可以創(chuàng)建不同實例的服務(wù)
之前我們說到,所有的服務(wù)的實例都是引用對象,無論被注入多少個控制器中,實際都指向同一個對象,所以,無論修改其中的哪一個,其它所有的服務(wù)都會被改變.這就是ng服務(wù)的設(shè)計模式,一般不需要去改變,但如果有特殊需要,要能夠每次注入控制器后得到新的實例,可以這樣做:
我們給服務(wù)添加了一個方法,每次執(zhí)行一次這個方法,都會創(chuàng)建一個新的實例,這樣,雖然在控制器里注入的是服務(wù)實例還是同一個,但是在調(diào)用創(chuàng)建實例方法的時候,都會創(chuàng)建一個新的實例,然后就可以單獨修改這個實例,而不會影響到其它控制器:如下
js:
varserviceApp
=
angular.module("serviceApp",[]);serviceApp.controller("myCtrl",function($scope,myConfig){varmyConfigConstant
= myConfig.create();? ? $scope.name = myConfigConstant.name;
$scope.age = myConfigConstant.age;
angular.extend(myConfigConstant,{love:"zxg"});? ? $scope.love =
myConfigConstant.love;? ? $scope.id = myConfigConstant.getId();
$scope.$watch(myConfigConstant.name,function(){$scope.name =
myConfigConstant.name;});? ? myConfigConstant.name =
"white_bunny";});serviceApp.controller("myOtherCtrl",function($scope,myConfig){varmyConfigConstant
= myConfig.create();? ? $scope.love = myConfigConstant.love;
$scope.name = myConfigConstant.name;
$scope.$watch(myConfigConstant.name,function(){$scope.name =
myConfigConstant.name;});});/************************創(chuàng)建實例的服務(wù)************************/serviceApp.factory("myConfig",function(){return{//服務(wù)返回的對象有一個create方法,該方法每次被執(zhí)行都會返回一個新的constructorFun實例create:
constructorFun.createNew
}});//創(chuàng)建一個構(gòu)造函數(shù)functionconstructorFun(){varmyname = "code_bunny";varage =
12;varid = 1;this.name = myname;this.age = age;this.id =
id}//給構(gòu)造函數(shù)添加createNew方法,用于實例化一個constructorFun.constructorFun.createNew
=function(){returnnewconstructorFun()};//給構(gòu)造函數(shù)添加原型的方法.使得它的實例可以繼承.constructorFun.prototype
= {? ? getId:function(){returnthis.id? ? }};