剛接觸Angular的時候覺得它的模塊化讓人非常不適應,并且使用TypeScript編寫后更是提升了一些學習曲線,在感覺高大上的同時一頭霧水摸不清。仔細學習和研究了之后發現要使用好Angular,對應用的架構要求具有高度組織性和層次性,但初學者非常容易在邏輯和文件層面出現組織混亂。為了理清這種混淆,首先得明確NgModule的概念。
NgModule
Angular賴以實現模塊化開發和構建應用的方式就是定義了自身框架的模塊化系統NgModule。對模塊化如此強調的原因有開發者意識層面的原因,也有實踐層面的原因,在Angular中尤其關鍵,邏輯層面的功能組織都是圍繞模塊來展開的。NgModule的含義有廣狹之分,廣義的概念就是指代Angular框架中的模塊體系,狹義的概念是Angular框架中最基礎的構建單元,即Angular應用是由一個個NgModule組成的,它具有代碼實體。
作用
NgModule最主要的用途就是在邏輯層面上組織代碼,它也體現在文件組織上。
-
模塊化:將實現一個具體功能集或特性的各部分歸集到一個模塊中,達到邏輯上的模塊化,可以通過對這個模塊進行導入和刪除而引用和移除這個模塊的功能。模塊可以包含多個組件和服務。這個模塊具體做了以下事情:
- 引入其他模塊導出的內容
- 聲明模塊包含的各部分內容
- 為模塊內各部分提供統一的編譯上下文
- 導出本模塊可供其他模塊依賴的內容
代碼組織:除了在邏輯層面上進行組織,文件目錄中也能體現這種模塊化的代碼組織方式,一個模塊可以體現為一個目錄,通過添加和移除目錄來實現這部分代碼的引入和刪除,做整體化的模塊增減。文件夾中包含了模塊文件、入口組件和路由文件,然后再通過子層的組件文件夾去實現具體的視圖或其他功能。一個文件組織非常到位的實例是ngx-admin,具體的文件組件方式也要根據應用的復雜程度來調整。另外官方已經推薦了比較好的實踐范式,這篇文章中最后整理出的體系圖可以為開發者提供一個最佳實踐的示意圖。
內容
-
組件:組件與Vue中的組件含義略有差異。在Angular中,組件的作用被要求更加單純,主要是模板和數據視圖的中間層,定義與視圖有關的邏輯,它通過文件夾的方式組織起來,組成的構建塊分別有html模板、css文件和ts視圖邏輯文件。盡管不把服務等與視圖無關的邏輯按文件拆分開來放也不影響最終的應用實現,但Angular希望能讓組件與服務這些用裝飾器實現的聲明類在邏輯層面上各司其職,在文件組織層面上各就其位。根據構建單元的引用層級,組件一般還包含了以下部分:
- 模板:與組件關聯的html文件
- 指令:Angular提供的結構化指令如
*ngIf
、*ngFor
,插值模板指令如ngModel
,可自定義 - 管道:格式化顯示插值
- 服務:與視圖無關并可跨組件共享的功能模塊。
NgModule與ES Module
ES Module是語言語法層面上的模塊體系,NgModule是Angular邏輯框架層面上的模塊體系,這兩個模塊系統的層面不同,是無沖突的。簡而言之,ES Module的使用以文件為單位,在其他框架構建的應用中與NgModule毫無關聯。
在Angular應用中,模塊的實現依賴于這兩個模塊系統的結合,是相輔相成的。由于NgModule是框架自身以邏輯實現的,與文件的綁定并無嚴格關系,模塊導入這種語法層面的事情還是得需要ES Module來處理,所以通過分析,可以很顯然得出結論,ES module處理文件依賴關系,NgModule處理應用邏輯依賴關系。
裝飾器
Angular架構中使用JS特性最突出的一點就是類,所有邏輯功能單元都被聲明為類,模塊、組件、服務、指令、管道等都是作為類來導出,而這些類本身是沒有辦法區分彼此,難道都只能通過口頭約定么?
另一個特性裝飾器無疑為這個問題提供了一個近乎完美的解決方案,裝飾器這個概念的引入得益于其他高級語言,而且這個方案的應用早就很成熟了,Python里就屢見不鮮。之前在學習ES6特性的時候一直覺得此特性只可遠觀,通過學習Angular的一番實踐,終于知道它是多么強大的開發助攻了。
在Angular所有的構建單元聲明前都要包裝一層裝飾器,元數據作為一個對象傳入裝飾器中用來在內部邏輯中將類和聲明的另一些構建塊(如模板、樣式)和構建單元建立關聯,同時明確這個類的身份。這樣在構建單元相互引用依賴時,就能區別引入的構建單元的類型,同時會制約它們的行為。
Angular應用的基礎架構
裝飾器是Angular架構中高層的抽象機制它區別了Angular中聲明類的類別,NgModule是邏輯層面的組織結構,它與裝飾器一起構筑了整個Angular應用架構的基石。