AngularJS:何時應(yīng)該使用Directive器钟、Controller津坑、Service?

(這篇文章你們一定要看傲霸,尤其初學(xué)的人国瓮,好嗎親?)
大漠窮秋
??AngularJS是一款非常強大的前端MVC框架。同時乃摹,它也引入了相當(dāng)多的概念禁漓,這些概念我們可能不是太熟悉。(譯者注:老外真謙虛孵睬,我大天朝的碼農(nóng)對這些概念那是相當(dāng)熟悉安ゼ摺!)這些概念有:

  • Directive(指令)
  • Controller(控制器)
  • Service (服務(wù))

下面我們逐個來看這些概念掰读,研究一下為什么它們會像當(dāng)初設(shè)計的那樣強大秘狞,同時研究一下為什么我們要以那樣的方式去使用它們。我們從Service開始蹈集。


SERVICES(服務(wù))

??如果你已經(jīng)使用過AngularJS烁试,你可能已經(jīng)遇到過Service這個概念了,簡而言之拢肆,Service就是【單例對象】在AngluarJS中的一個別名减响。這些小東西(指單例對象)會被經(jīng)常傳來傳去,保證你每次訪問到的都是同一個實例郭怪,這一點和工廠模式不同支示。基于這種思想鄙才,單例對象讓我們可以實現(xiàn)一些相當(dāng)酷的功能颂鸿,它可以讓很多controller和directive訪問內(nèi)部的數(shù)值。這也是非常常見的問題之一攒庵,那就是在應(yīng)用中的不同代碼塊之間如何共享數(shù)據(jù)嘴纺?我們來看這個問題。

我們首先來創(chuàng)建一個module(模塊)浓冒,本文中的所有代碼都會用到這個module栽渴。

var module = angular.module( "my.new.module", [] );

下一步,我們來創(chuàng)建一個新的service(服務(wù))裆蒸。假設(shè)我們上面的這個module是用來管理圖書的熔萧。所以糖驴,這里我們來創(chuàng)建一個Book service僚祷,然后把一個JSON對象數(shù)組添加到這個serice中,這些對象代表很多book數(shù)據(jù)贮缕。

module.service( 'Book', [ '$rootScope', function( $rootScope ) { 
    var service = { 
      books: [ 
        { title: "Magician", author: "Raymond E. Feist" }, 
        { title: "The Hobbit", author: "J.R.R Tolkien" } 
      ], 

      addBook: function ( book ) { 
        service.books.push( book ); 
        $rootScope.$broadcast( 'books.update' ); 
      } 
    } 
    return service;
}]);

??這是一個非常簡單的service(有時候這樣就夠你用了)辙谜。我們這里正在做的事情就是在管理一個book 數(shù)組,同時還帶有一個addBook方法感昼,在有需要的時候可以添加更多書籍装哆。addBook方法還會在application上廣播一個事件,告訴所有正在使用我們的service的人,數(shù)組已經(jīng)被更新了蜕琴,從而讓它們自己也做一些刷新操作∑甲溃現(xiàn)在,我們要做的就是把這個service傳遞給各種controller凌简、directive上炎、filter,或者其它任何需要它的東西---然后它們就可以訪問service中的這些方法和屬性了雏搂。好藕施,我們來動手。

var ctrl = [ '$scope', 'Book', function( scope, Book ) { 
  scope.$on( 'books.update', function( event ) { 
    scope.books = Book.books; 
  }); 
  scope.books = Book.books; 
}]; 

module.controller( "books.list", ctrl );

??同樣非常簡單凸郑。我們上面所做的就是為我們的module創(chuàng)建了一個新的controller裳食。在創(chuàng)建的時候把$scope provdier和我們自己的Book service傳遞給了它。能明白我們在干嘛嗎芙沥?我們把前面創(chuàng)建的Book service中的books數(shù)組賦給了controller內(nèi)部的局部scope對象诲祸。很酷,對吧憨愉?

??好烦绳,這里的核心問題是什么呢?我們節(jié)省了一些時間配紫,并且在controller上創(chuàng)建了一個數(shù)組径密。對---我們確實這樣做了。這樣做確實也為我們節(jié)約了一點時間---但是如果我們要在其它地方處理這些書籍信息應(yīng)該怎么辦呢躺孝?通過scope來維護數(shù)據(jù)是非常粗暴的一種方式享扔。由于其它controller、directive植袍、model的影響惧眠,scope很容易就會崩潰或者變臟。它很快就會變成一團亂麻于个。通過一種集中的途徑(在這里就是service)來管理所有書籍?dāng)?shù)據(jù)氛魁,然后通過某種方式來請求修改它,這樣不僅僅會更加清晰---同時當(dāng)應(yīng)用的體積不斷增大的時候也更加容易管理厅篓。最后秀存,它還可以讓你的代碼保持模塊化(這也是Angular很擅長的一件事情)。一旦你在其它項目中需要用到這個service羽氮,你沒有必要在scope或链、controller、filter等等東西里面到處去查找相關(guān)的代碼档押,因為所有東西都在service里面澳盐!

??好祈纯。那么我們什么時候應(yīng)該使用service呢?答案是:無論何時叼耙,當(dāng)我們需要在不同的域中共享數(shù)據(jù)的時候腕窥。另外,多虧了Angular的依賴注入系統(tǒng)筛婉,實現(xiàn)這一點是很容易并且很清晰的油昂。


CONTROLLERS(控制器)

??我們再來看控制器!除非你曾經(jīng)使用過前端MVC倾贰,否則從服務(wù)端MVC的思維模式轉(zhuǎn)向客戶端MVC的思維模式就如同一次腦筋急轉(zhuǎn)彎冕碟。為什么會這樣呢?這是因為匆浙,雖然在前端開發(fā)中controller實現(xiàn)了非常類似的功能安寺,但是它同時還會實現(xiàn)一些與服務(wù)端controller非常不同的功能。在Angular中首尼,controller自身并不會處理"request"挑庶,除非它是用來處理路由(route)的(很多人把這種方式叫做創(chuàng)建route controller---路由控制器),更明確地說软能,尤其是你的應(yīng)用里面那些作為界面的一部分的controller迎捺,它們只會管理非常小的一段代碼。

??controller應(yīng)該純粹地用來把service查排、依賴關(guān)系凳枝、以及其它對象串聯(lián)到一起,然后通過scope把它們關(guān)聯(lián)到view上跋核。如果在你的視圖里面需要處理復(fù)雜的業(yè)務(wù)邏輯岖瑰,那么把它們放到controller里面也是一個非常不錯的選擇∩按回到我們前面的這個books例子蹋订,我實際上并沒有什么東西需要添加到controller里面。

??但是Kirk(譯者注:指本文原作者)刻伊,如果我要add一本書籍應(yīng)該怎么辦呢露戒?我應(yīng)該在controller上面新增一個方法來處理這件事情嗎?不捶箱,原因在下面解釋智什。因為它是DOM交互/操作的一部分。所以請把它放到directive(指令)里面讼呢。怎么做呢撩鹿?很高興你能問出這個問題谦炬。


DIRECTIVES(指令)

??到目前為止悦屏,在我們所編寫的大量AngularJS應(yīng)用中节沦,應(yīng)用中最主要的復(fù)雜部分都在directive(指令)中。有一個強大的工具可以用來操作和修改DOM础爬,它也是我們這里需要討論的內(nèi)容甫贯。我們來提供一個按鈕,用戶通過它可以向service里面添加一本圖書看蚜,以這一功能來結(jié)束此文叫搁。

??一個常見的反模式是在controller里面添加DOM交互代碼。Angular對directive的定義是一段代碼片段供炎,你可以用它來操作DOM渴逻,但是我覺得directive也是進行用戶交互的很好選擇。我們來擴展前面的例子音诫,為用戶提供一個按鈕惨奕,通過這個按鈕可以向service里面添加一本書籍。

module.directive( "addBookButton", [ 'Book', function( Book ) { 
    return { 
        restrict: "A", 
        link: function( scope, element, attrs ) { 
          element.bind( "click", function() { 
            Book.addBook( { title: "Star Wars", author: "George Lucas" } ); 
          }); 
        }
    }
}]);

很簡單的東西竭钝。我們創(chuàng)建了一個指令梨撞,它的核心目的是簡單地向books列表中添加一本書籍,books已經(jīng)注冊在了我們的Book服務(wù)中香罐。我們來把這個指令應(yīng)用到我們的視圖中卧波。

<button add-book-button>Add book</button>

如你所見,我們僅僅把指令當(dāng)作一個元素屬性來使用庇茫。每次點擊這個按鈕的時候港粱,它都會把《Star Wars》(《星球大戰(zhàn)》)這本書添加到我們的Book service中去。簡單旦签、輕松啥容、模塊化---并且易復(fù)用。好了顷霹,我們?yōu)槭裁床恢苯釉诳刂破魃厦嫣砑右粋€addBook之類的方法呢咪惠,比如說就像下面這樣:

$scope.addBook = function() { 
    Book.addBook( { title: "Star Wars", author: "George Lucas" } ); 
};

這樣我們也能獲得同樣的結(jié)果,對吧淋淀?是的遥昧,確實如此---但是這樣做會帶來一個重大的問題。一旦我需要在其它地方添加書籍朵纷,我必須拷貝這份代碼(非常un-DRY!)(譯者注:DRY---Dont Repeat Yourself炭臭,貌似是Ruby所倡導(dǎo)的一個重要的編碼原則。)袍辞,或者進行重構(gòu)(重構(gòu)本身并不是什么不好的的事情)鞋仍。通過直接構(gòu)建一個指令的方式,我們以后就沒有必要擔(dān)心這種事情了---同時下次再需要實現(xiàn)相同功能的時候完全不需要花任何時間搅吁。通過構(gòu)建指令的方式來進行DOM交互和修改威创,隨著業(yè)務(wù)需求的不斷介入落午,我們就可以立即騰出手來處理復(fù)雜性不斷增加的應(yīng)用了。這是相當(dāng)不錯的一件事情肚豺,因為它保證了我們可以更少地和自己的實現(xiàn)打架溃斋,并且可以一直編寫DRYer code。

??Angular的模塊依賴哲學(xué)無疑讓它成為了一款非同凡響的框架吸申。它讓我們能夠以這樣一種方式來編寫我們的前端代碼:我們不會干翻自己梗劫,也不會干翻框架---這可能是它最強大的力量。
希望我已經(jīng)充分說明了你應(yīng)該在何時何地使用這幾個Angular概念截碴,從而能夠更好地編寫你自己的代碼梳侨。
原文鏈接:
http://kirkbushell.me/when-to-use-directives-controllers-or-services-in-angular/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市日丹,隨后出現(xiàn)的幾起案子猫妙,更是在濱河造成了極大的恐慌,老刑警劉巖聚凹,帶你破解...
    沈念sama閱讀 212,185評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件割坠,死亡現(xiàn)場離奇詭異,居然都是意外死亡妒牙,警方通過查閱死者的電腦和手機彼哼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,445評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來湘今,“玉大人敢朱,你說我怎么就攤上這事∧ο梗” “怎么了拴签?”我有些...
    開封第一講書人閱讀 157,684評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長旗们。 經(jīng)常有香客問我蚓哩,道長,這世上最難降的妖魔是什么上渴? 我笑而不...
    開封第一講書人閱讀 56,564評論 1 284
  • 正文 為了忘掉前任岸梨,我火速辦了婚禮,結(jié)果婚禮上稠氮,老公的妹妹穿的比我還像新娘曹阔。我一直安慰自己,他們只是感情好隔披,可當(dāng)我...
    茶點故事閱讀 65,681評論 6 386
  • 文/花漫 我一把揭開白布赃份。 她就那樣靜靜地躺著,像睡著了一般奢米。 火紅的嫁衣襯著肌膚如雪抓韩。 梳的紋絲不亂的頭發(fā)上纠永,一...
    開封第一講書人閱讀 49,874評論 1 290
  • 那天,我揣著相機與錄音园蝠,去河邊找鬼。 笑死痢士,一個胖子當(dāng)著我的面吹牛彪薛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播怠蹂,決...
    沈念sama閱讀 39,025評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼善延,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了城侧?” 一聲冷哼從身側(cè)響起易遣,我...
    開封第一講書人閱讀 37,761評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嫌佑,沒想到半個月后豆茫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,217評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡屋摇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,545評論 2 327
  • 正文 我和宋清朗相戀三年揩魂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炮温。...
    茶點故事閱讀 38,694評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡火脉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出柒啤,到底是詐尸還是另有隱情倦挂,我是刑警寧澤,帶...
    沈念sama閱讀 34,351評論 4 332
  • 正文 年R本政府宣布担巩,位于F島的核電站方援,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏涛癌。R本人自食惡果不足惜肯骇,卻給世界環(huán)境...
    茶點故事閱讀 39,988評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望祖很。 院中可真熱鬧笛丙,春花似錦、人聲如沸假颇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,778評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽笨鸡。三九已至姜钳,卻和暖如春坦冠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哥桥。 一陣腳步聲響...
    開封第一講書人閱讀 32,007評論 1 266
  • 我被黑心中介騙來泰國打工辙浑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拟糕。 一個月前我還...
    沈念sama閱讀 46,427評論 2 360
  • 正文 我出身青樓判呕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親送滞。 傳聞我的和親對象是個殘疾皇子侠草,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,580評論 2 349

推薦閱讀更多精彩內(nèi)容