AngularJS應(yīng)用開發(fā)思維之依賴注入3
找不到的API?
AngularJS提供了一些功能的封裝,但是當(dāng)你試圖通過全局對象angular去 訪問這些功能時(shí),卻發(fā)現(xiàn)與以往遇到的庫大不相同。
$http
比如,在jQuery中,我們知道它的API通過一個(gè)全局對象:$ 暴露出來,當(dāng)你需要 進(jìn)行ajax調(diào)用時(shí),使用$.ajax()就可以了。這樣的API很符合思維的預(yù)期。
AngularJS也暴露了一個(gè)全局對象:angular,也對ajax調(diào)用進(jìn)行封裝提供了一個(gè) $http對象,但是,但是,當(dāng)你試圖沿用舊經(jīng)驗(yàn)訪問angular.$http時(shí),發(fā)現(xiàn)不是 那么回事!
仔細(xì)地查閱$http的文檔,也找不到一點(diǎn)點(diǎn)的線索,從哪里可以把這個(gè)$http拿到。
依賴注入/DI
事實(shí)上,AngularJS把所有的功能組件都以依賴注入的方式組織起來:
在依賴注入的模式下,所有的組件必須通過容器才能相互訪問,這導(dǎo)致了在AngularJS中, 你必須通過一個(gè)中介才能獲得某個(gè)組件的實(shí)例對象:
var injector = angular.injector(['ng']); injector.invoke(function($http){ //do sth. with $http });
這個(gè)中介,就是依賴注入模式中的容器,在AngularJS中,被稱為:注入器。
在→_→的示例中,我們可以看到,我們已經(jīng)拿到了$http對象,它其實(shí)是一個(gè)函數(shù)。
注入器/injector
注入器是AngularJS框架實(shí)現(xiàn)和應(yīng)用開發(fā)的關(guān)鍵,這是一個(gè)DI/IoC容器的實(shí)現(xiàn)。
AngularJS將功能分成了不同類型的組件分別實(shí)現(xiàn),這些組件有一個(gè)統(tǒng)稱 - 供給者/provider, 下圖中列出了AngularJS幾個(gè)常用的內(nèi)置服務(wù):
AngularJS的組件之間不可以互相直接調(diào)用,一個(gè)組件必須通過注入器才 可以調(diào)用另一個(gè)組件。這樣的好處是組件之間相互解耦,對象的整個(gè)生命周期的管理 甩給了注入器。
注入器實(shí)現(xiàn)了兩個(gè)重要的功能:
集中存儲(chǔ)所有provider的配方
配方其實(shí)就是:名稱+類構(gòu)造函數(shù)。AngularJS啟動(dòng)時(shí),這些provider首先使用其配方在注入器 內(nèi)注冊。比如,http請求服務(wù)組件封裝在$httpProvider類內(nèi),它通過'$http'這個(gè)名字在注入 器內(nèi)注冊。
按需提供功能組件的實(shí)例
其他組件,比如一個(gè)用戶的控制器,如果需要使用http功能,使用'$http'這個(gè)名字 向注入器請求,就可以獲得一個(gè)http服務(wù)實(shí)例了。
試著修改→_→的代碼,查看下$compile服務(wù)到底是什么?
注冊服務(wù)組件
從injector的角度看,組件就是一個(gè)功能提供者,因此被稱為供給者/Provider。 在AngularJS中,provider以JavaScript類(構(gòu)造函數(shù))的形式封裝。
服務(wù)名稱通常使用一個(gè)字符串標(biāo)識(shí),比如'$http'代表http調(diào)用服務(wù)、'$rootScope'代表根 作用域?qū)ο蟆?$compile'代表編譯服務(wù)...
Provider類要求提供一個(gè)$get函數(shù)(類工廠),injector通過調(diào)用該函數(shù), 就可以獲得服務(wù)組件的實(shí)例。
名稱和類函數(shù)的組合信息,被稱為配方。injector中維護(hù)一個(gè)集中的配方庫, 用來按需創(chuàng)建不同的組件。這個(gè)配方庫,其實(shí)就是一個(gè)Hash對象,key就是服務(wù)名稱,value 就是類定義。
在→_→的示例中,我們定義了一個(gè)簡單的服務(wù)類,這個(gè)服務(wù)類的實(shí)例就是一個(gè)字符串:“hello,world!”。 我們使用'ezHello'作為其服務(wù)名在注入器里注冊,并通過注入器將這個(gè)實(shí)例顯示出來。
獲得注入器對象
要使用AngularJS的功能,必須首先獲取注入器。有兩種方法取得注入器。
創(chuàng)建一個(gè)新的注入器
可以使用angular.injector()創(chuàng)建一個(gè)新的注入器:
angular.injector(modules, [strictDi]); 獲取已經(jīng)創(chuàng)建的注入器
如果AngularJS框架已經(jīng)啟動(dòng),那么可以使用DOM對象的injector()方法獲 得已經(jīng)創(chuàng)建的注入器:
var element = angular.element(dom_element);
var injector = element.injector();
通過注入器調(diào)用API
注入器有兩個(gè)方法可供進(jìn)行API調(diào)用:invoke()和get()。
invoke()
使用注入器的invoke()方法,可以直接調(diào)用一個(gè)用戶自定義的函數(shù)體,并通過函數(shù)參數(shù) 注入所依賴的服務(wù)對象,這是AngularJS推薦和慣例的用法:
angular.injector(['ng']) .invoke(function($http){ //do sth. with $http }); get()
也可以使用注入器的get()方法,獲得指定名稱的服務(wù)實(shí)例:
var my$http = angular.injector(['ng']).get('$http'); //do sth. with my$http
→_→的示例這次使用了get()方法直接獲取一個(gè)服務(wù)實(shí)例,感受一下!
注入的方式和原理
有兩種方法告知注入器需要注入的服務(wù)對象:參數(shù)名注入和依賴數(shù)組注入。
參數(shù)名注入
AngularJS在執(zhí)行invoke()函數(shù)時(shí),將待注入函數(shù)定義轉(zhuǎn)化為字符串,通過 正則表達(dá)式檢查其參數(shù)表,從而發(fā)現(xiàn)并注入所所依賴的服務(wù)對象:
//myfunc通過參數(shù)表聲明這個(gè)函數(shù)依賴于'$http'服務(wù) var myfunc = function($http){ //do sth. with $http }; injector.invoke(myfunc);//myfunc的定義將被轉(zhuǎn)化為字符串進(jìn)行參數(shù)名檢查
這樣有一個(gè)問題,就是當(dāng)我們對JavaScript代碼進(jìn)行壓縮處理時(shí),$http可能會(huì)被 變更成其他名稱,這將導(dǎo)致注入失敗。
依賴數(shù)組注入
AngularJS采用依賴項(xiàng)數(shù)組的方法解決代碼壓縮混淆產(chǎn)生的問題。這時(shí)傳入invoke()的 是一個(gè)數(shù)組,數(shù)組的最后一項(xiàng)是實(shí)際要執(zhí)行的函數(shù),其他項(xiàng)則指明需要向該函數(shù)注入 的服務(wù)名稱。注入器將按照數(shù)組中的順序,依次向函數(shù)注入依賴對象。
采用這種方法,待注入函數(shù)的參數(shù)表的名稱就無關(guān)緊要了:
//myfunc依賴于'$http'和'$compile'服務(wù) var myfunc = ['$http','$compile',function(p1,p2){ //do sth. with p1($http),p2($compile) }]; injector.invoke(myfunc);
→_→的實(shí)例這次采用依賴數(shù)組的方法注入了ezHello服務(wù)實(shí)例,可以改改參數(shù)名稱 看有沒有影響結(jié)果?
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 利用VS Code開發(fā)你的第一個(gè)AngularJS 2應(yīng)用程序
- Angularjs單選改為多選的開發(fā)過程及問題解析
- AngularJS框架中的雙向數(shù)據(jù)綁定機(jī)制詳解【減少需要重復(fù)的開發(fā)代碼量】
- 基于NodeJS+MongoDB+AngularJS+Bootstrap開發(fā)書店案例分析
- AngularJS開發(fā)教程之控制器之間的通信方法分析
- Ubuntu系統(tǒng)下Angularjs開發(fā)環(huán)境安裝
- 總結(jié)AngularJS開發(fā)者最常犯的十個(gè)錯(cuò)誤
- 利用Angularjs和Bootstrap前端開發(fā)案例實(shí)戰(zhàn)
- angularJS開發(fā)注意事項(xiàng)
相關(guān)文章
深入解析Angular動(dòng)態(tài)導(dǎo)入和懶加載實(shí)例
這篇文章主要為大家深入解析了Angular動(dòng)態(tài)導(dǎo)入和懶加載實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10Ionic+AngularJS實(shí)現(xiàn)登錄和注冊帶驗(yàn)證功能
這篇文章主要介紹了Ionic+AngularJS實(shí)現(xiàn)登錄和注冊帶驗(yàn)證功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02Angular2 自定義表單驗(yàn)證器的實(shí)現(xiàn)方法
這篇文章主要介紹了Angular2 自定義表單驗(yàn)證器的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12淺談angular表單提交中ng-submit的默認(rèn)使用方法
今天小編就為大家分享一篇淺談angular表單提交中ng-submit的默認(rèn)使用方法。具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09淺談Angular2 ng-content 指令在組件中嵌入內(nèi)容
本篇文章主要介紹了淺談Angular2 ng-content 指令在組件中嵌入內(nèi)容,具有一定的參考價(jià)值,有興趣的可以了解一下2017-08-08