在Angular中,控制器應(yīng)該是簡(jiǎn)潔精煉的耸彪;一些邏輯和重復(fù)性的數(shù)據(jù)都應(yīng)該要存儲(chǔ)到服務(wù)中伞芹。控制器就應(yīng)該在需要他們的時(shí)候?qū)嵗跄龋诓恍枰臅r(shí)候就取消掉唱较。因此,Angular在你每次切換路由的時(shí)候蜀肘,就會(huì)清理當(dāng)前的控制器绊汹。但是呢,服務(wù)為我們提供了一種長(zhǎng)期存儲(chǔ)應(yīng)用數(shù)據(jù)的方式扮宠,同時(shí)西乖,也可以在不同的控制器之間統(tǒng)一的使用服務(wù)。
Angular為我們提供了三種創(chuàng)建服務(wù)的方式:
- Factory
- Service
- Provider
廢話不多說(shuō)坛增,簡(jiǎn)要分析一下获雕。
factory新創(chuàng)建了一個(gè)對(duì)象,然后在這個(gè)對(duì)象上新添屬性收捣,最后返回這個(gè)對(duì)象届案。
service使用new關(guān)鍵詞進(jìn)行了實(shí)例化。只需要在this上添加屬性和方法罢艾,服務(wù)就會(huì)自動(dòng)的返回this楣颠。
factory與service在controller的用法并沒(méi)有什么不同尽纽,不要以為service每次注入controller都要new一次,AngularJS 在初始化的時(shí)候童漩,會(huì)new一次service,所以當(dāng) controller 要求注入 service 的時(shí)候弄贿,AngularJS 就會(huì)把已經(jīng) new 過(guò)的的 service 給 controller。
注意:Provider 都是 singleton !!!!!
沒(méi)錯(cuò)矫膨,所以就算 service 有 new 這個(gè)指令差凹,可是其實(shí)也只是做一次而已。
每個(gè)要求注入 service 的 components 拿到的都會(huì)是同一個(gè)service reference侧馅。
factory 也是相同的情況危尿,全部系統(tǒng)共用一個(gè) Factory reference。
所以我們才用Provider做controller之間傳值的橋梁D俪铡R杲俊!
Provider:
provider是唯一一種可以創(chuàng)建用來(lái)注入到config()函數(shù)的服務(wù)的方式罗晕。想在你的服務(wù)啟動(dòng)之前邮绿,進(jìn)行一些模塊化的配置的話,就使用provider攀例。
來(lái)簡(jiǎn)單的說(shuō)明一下 Provider 跟 Factory 和 Service 的關(guān)系。個(gè)人覺(jué)得 Mark Meyer 在 top 10 mistakes angularjs developers make 文章解說(shuō)的很好顾腊。把 code 借來(lái)并附上我的注解粤铭。
// factory 的底層就是回傳 provider 的 $get 裡的值
function factory(name, factoryFn) {
return provider(name, { $get: factoryFn });
}
// service 的底層就是在 factory 裡使用 $jnjector.instantiate 跟 construct 建立新物件
// ( $injector.instantiate 會(huì)做 new instance 的動(dòng)作)
function service(name, constructor) {
return factory(name, ['$injector',
function($injector) {
return $injector.instantiate(constructor);
}]);
}
再來(lái)看看provider的使用方式:
app.provider('My', function () {
// 私有屬性和方法
var artist;
// 只有直接添加在this上的屬性才能被config函數(shù)訪問(wèn)
this._artist = '';
this.thingFromConfig = '';
// 只有$get函數(shù)返回的屬性才能被控制器訪問(wèn)
this.$get = function () {
var that = this;
return {
getArtist: function () {
return that._artist;
},
thingFromConfig: that.thingFromConfig
};
};
})
.config(['MyProvider', function ( MyProvider ) {
MyProvider.thingFromConfig = 'this is set in config()';
}])
.controller('myProviderCtrl', [
'$scope', 'My',
function ( $scope, My ) {
$scope.artist = My.thingFromConfig;
}]);
你可以認(rèn)為provider有三個(gè)部分,第一部分是私有變量和私有函數(shù)杂靶,這些變量和函數(shù)會(huì)在以后被修改梆惯。第二部分是在app.config函數(shù)里可以訪問(wèn)的變量和函數(shù),所以吗垮,他們可以在在其他地方使用之前被修改垛吗。注意,這些變量和函數(shù)一定要添加到this上面才行烁登。在我們的例子中怯屉,app.config()函數(shù)能夠修改的只有thingFromConfig。第三部分是在控制器里可以訪問(wèn)的變量和函數(shù)饵沧。
當(dāng)使用 provider創(chuàng)建服務(wù)的時(shí)候锨络,唯一可以讓控制器訪問(wèn)的屬性和方法是在$get()函數(shù)里返回的屬性和方法。將$get添加到了this上面狼牺,最終這個(gè)函數(shù)會(huì)被返回羡儿。