一、服務 服務提供了一種能在應用的整改生命周期內保持數據的方法,它能夠在控制器之間進行通信,並保持數據的一致性。 1.服務是一個單例對象,在每個應用中只會被實例化一次(被$injector); 2.服務提供了把與特定功能相關連的方法集中在一起的介面,實際中用於封裝通用方法,請求後臺數據,處理數據返回 ...
一、服務
服務提供了一種能在應用的整改生命周期內保持數據的方法,它能夠在控制器之間進行通信,並保持數據的一致性。
1.服務是一個單例對象,在每個應用中只會被實例化一次(被$injector);
2.服務提供了把與特定功能相關連的方法集中在一起的介面,實際中用於封裝通用方法,請求後臺數據,處理數據返回給控制器;
3.服務被註冊後就可以引用它,併在運行時把它當做依賴載入進來。
二、創建服務的5種方式
1.factory服務
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 } } });
2.service服務
使用service()可以註冊一個支持構造函數的服務
app.service('name',constructor)
name為服務的名字,constructor是一個構造函數.
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 } });
3.provider服務
所以服務工廠都是由$provide服務創建的,所有創建服務的方法都是構建在provider方法之上。
name為服務的名字,第二個參數接受一個函數,函數返回一個對象,返回的對象比如要有$get方法,$get方法必須要返回一個對象obj,這個對象就是真正被註入的服務.
provider服務的第二個參數的返回值中必須要有$get方法(除了$get,還可以有其它方法,後面的例子會說到),$get方法就相當於factory服務的第二個參數,最後要返回一個對象,這個對象就是真正被註入的服務:
app.provider('name',function(){ .... return { ... $get:function(){ ... return obj } } })
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 } } } } });
這兩種寫法和之前是一樣的,之前的可以看成是它的簡略寫法。
我們只有希望在config()函數中對服務進行配置時,那就必須使用provider()來定義服務了。
serviceApp.provider('myConfig',function(){ var id = 1; return { setID:function(newID){ id = newID }, $get:function(){ var myname = 'code_bunny'; var age = 12; return { name: myname, age: age, getId: function(){ return id } } } } }); serviceApp.config(function(myConfigProvider){ myConfigProvider.setID(2) });
說明:
這裡的provider服務不僅僅返回了$get方法,還返回了setID方法,然後id變數是寫在函數里的,返回值的外面,形成一個閉包,可以被修改.
然後,在provider服務里定義的方法,可以在config函數里調用.註意調用的格式:
serviceApp.config(function(myConfigProvider){ myConfigProvider.setID(2) });
被註入的服務名不叫myConfig,而是myConfigProvider.然後在函數裡面可以調用myConfigProvider的setID方法(也就是myConfig的setID方法).
通過這種方式,使得我們的服務可以被手動配置,比如這裡可以配置id.
ng有很多內置的服務都有這樣的功能,比如$route服務,$location服務,當我們通過$routeProvider和$locationProvider來配置的時候,其本質就是這些服務是通過provider創建的.
4.constant服務
constant()一般將常量保存下來
app.constant('name',obj)
name為服務的名字,obj為一個json對象.
serviceApp.constant('myConfig',{ name:'code_bunny', age:12, getId:function(){ return 1 } });
constant創建服務返回一個json對象(也就是第二個參數中傳入的對象),這個對象里可以有參數,可以有方法,並且,屬性和方法都可以在控制器中修改,新增,但是按照它的設計本意,一般constant創建的服務不會去修改它的內容,需要修改內容,最好用value來創建服務.
5.value服務
app.value('name',obj)
name為服務的名字,obj為一個json對象.
serviceApp.value('myConfig',{ name:'code_bunny', age:12, getId:function(){ return 1 } });
value創建服務返回一個json對象(也就是第二個參數中傳入的對象),這個對象里可以有參數,可以有方法,並且,屬性和方法都可以在控制器中修改,新增,按照它的設計本意,如果屬性和方法需要被修改內容,就用value來創建服務.
constant和value主要就是用於存放一些數據或方法以供使用,區別是constant一般是存放固定內容,value存放可能會被修改的內容
6.裝飾服務decorator
$provide服務提供了在服務實例創建時對其進行攔截的功能,可以對服務進行擴展或者替代等。
serviceApp.value('myConfig',{ name:'code_bunny', age:12, getId:function(){ return 1 } });
serviceApp.config(function($provide){ $provide.decorator('myConfig',function($delegate){ $delegate.money = '100w'; return $delegate }) });
同樣是通過config,在參數函數中註入$provider服務,$provider服務有個decorator方法,它接受兩個參數,第一個參數'name',是要被裝飾的服務的名字,第二個參數是一個函數,函數中註入$delegate,$delegate就是被裝飾的服務的實例,然後在函數中操作$delegate,就相當於操作了該服務的實例.
註意:
1.最後一定要return $delegate,這樣服務才算被裝飾完成了.
2.constant服務是不能被裝飾的.
總結上面的內容:
1.服務的實例被註入到控制器以後,都是一個引用對象,無論被註入多少個控制器中,實際都指向同一個對象,所以,無論修改其中的哪一個,其它所有的服務都會被改變.
2.服務的實例被修改過後,ng不會自動同步,需要使用$scope.$watch()監測其變化並手動刷新視圖.
3.constant服務不能通過decorator進行裝飾.
4.一些固定的參數和方法,使用constant
5.可能被修改的參數和方法,使用value
6.通過邏輯處理後得到的參數或方法,使用factory
7.可以使用factory的也可以使用service,反之亦然(一般就是用factory)
8.可以手動配置參數的服務,使用provider