NgModule 模塊是Angular種一個重要的點,由於Angular的基本構造塊就是NgModule。NgModule 會把相關的代碼收集到一些功能集中,造成功能單元。在使用Angular CL 命令新建一個項目的時候,會給咱們生成一個根模塊,命名爲 AppModule,根模塊有一個根組件AppComponent,引導這個根模塊就能夠啓動應用。
Angular 應用是模塊化的,咱們在開發中會根據其功能 做用 以及其特性,創建大大小小各類模塊,從而構建其成爲一個應用程序,任何模塊都能包含任意數量的其它組件。css
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
由⬆️代碼咱們能夠看到,NgModule 是一個帶有 @NgModule()
裝飾器的類,它接受一個元數據對象,該對象的屬性用來描述這個模塊。html
點進去@NgModule()
裝飾器的類咱們能夠看到他有以下屬性以及官方的對其屬性的解釋。
npm
export declare interface NgModule { providers?: Provider[];// 本模塊向全局服務中貢獻的那些服務的建立器。 這些服務能被本應用中的任何部分使用。(你也能夠在組件級別指定服務提供商,這一般是首選方式。) declarations?: Array<Type<any> | any[]>;// 那些屬於本 NgModule 的組件、指令、管道 imports?: Array<Type<any> | ModuleWithProviders<{}> | any[]>;// 那些導出了本模塊中的組件模板所需的類的其它模塊 exports?: Array<Type<any> | any[]>;//那些能在其它模塊的組件模板中使用的可聲明對象的子集 entryComponents?: Array<Type<any> | any[]>; bootstrap?: Array<Type<any> | any[]>; schemas?: Array<SchemaMetadata | any[]>; }
如下是本人使用Angular後對此元數據屬性我的口語化的理解bootstrap
providers:將本模塊全部在組件中注入的服務,在這裏提早定義好,不然在此模塊中使用這個服務會有錯誤提示。api
declaration:declaration 英文意思爲聲明。在這裏聲明一些模塊中要使用到的一些組件,指令,管道等。瀏覽器
imports:導入一些模塊,好比說我把全部的指令構成一個模塊 我使用其中某些指令的時候,我能夠選擇導入整個指令模塊。也能夠導入一些經過npm install 安裝的一些模塊導入其中,纔可使用。服務器
exports:導出組件or指令管道等,以供引用此模塊的模塊可使用此模塊的組件or 指令管道等。app
exporyComponents:entry component 表示 angular 的入口組件,能夠引導組件是一個入口組件,Angular 會在引導過程當中把它加載到 DOM 中。 其它入口組件是在其它時機動態加載的。字面上的意義,可是啥時候用呢,好比,我要彈出一個組件,那麼這個組件是要動態加載到DOM中了吧,這個時候就須要將這個組件xxxComponent寫上了。ide
bootstrap:這個模塊啓動的時候應該啓動的組件,上面代碼能夠看到AppModule是做爲根模塊的啓動組件。模塊化
schemas:不屬於Angular的組件或者指令的元素或者屬性都須要在這裏進行聲明。
JavaScript 和 Angular 都使用模塊來組織代碼,雖然它們的組織形式不一樣,但 Angular 的應用會同時依賴二者。
JavaScript 模塊:
模塊是內含 JavaScript 代碼的獨立文件。要讓其中的東西可用,要寫一個導出語句
例:
export class AppComponent { ... }
在其餘文件中須要使用
import { AppComponent } from './app.component';
而NgModulem模塊咱們在隨筆的開頭以及介紹他的元數據,對其有必定的瞭解了。
NgModule 類 與 JavaScript 模塊有下列關鍵性的不一樣:
1.NgModule 只綁定了可聲明的類,這些可聲明的類只是供 Angular 編譯器用的。
2.NgModule 與 JavaScript 類把它全部的成員類都放在一個巨型文件中不一樣,只要把該模塊的類列在它的 @NgModule.declarations 列表中。
3.NgModule 只能導出可聲明的類。這多是它本身擁有的也多是從其它模塊中導入的。它不會聲明或導出任何其它類型的類。
4.與 JavaScript 模塊不一樣,NgModule 能夠經過把服務提供商加到 @NgModule.providers 列表中,來用服務擴展整個應用。
相比之下咱們能夠看出,NgModulem模塊更靈活,擴展性強,更具優點。
首先要知道跑起來一個項目須要引用什麼基本的模塊,如下是Angular 提供的一些官方的模塊。
NgModule |
導入自 |
爲什麼使用 |
---|---|---|
|
當你想要在瀏覽器中運行應用時 |
|
|
當你想要使用 |
|
|
當要構建模板驅動表單時(它包含 |
|
|
當要構建響應式表單時 |
|
RouterModule |
@angular/router |
要使用路由功能,而且你要用到 |
|
當你要和服務器對話時 |
官方文檔將模塊分爲五大類。
雖然我特麼當年根本不知道,可是在開發中慢慢摸索其實發現也是根據模塊的特性將模塊的分類,結果不經相同。
如下爲我的在開發中對功能模塊的劃分
1.業務型模塊:整一個應用程序,根據其業務功能咱們能夠將程序拆分爲一個個模塊,有很明確的業務特性,圍繞其業務功能的模塊。例如:用戶模塊,訂單模塊等。它有本身獨立的路由,有提供與此模塊的服務,有一個or多個組件,它惰性懶加載,不會導出or提供任何組件or指令管道,引用官方、本應用程序or第三方的功能模塊。它有明確的業務特性,不與別的模塊有耦合性。
2.組件模塊:應用程序中一般都有規範化的標準設計 ,好比說統一的table,card date 等。將這些都抽出來,作成一個個組件,在模塊中導出此組件以供其餘模塊使用,這樣減小了應用程序中重複的樣式代碼等。曾經我是將全部這種可能多處要使用的封裝爲組件後,統一在一個模塊中導出,後來演變爲每個組件都拆分爲一個模塊。這樣也是發現若是這種通用性的組件多起來的話,假設有二三十個組件在這個UIComponent模塊中,而我由於要使用其中一兩個組件而導入這個模塊,性能是不好的,因此後來都將組件拆分爲一個個模塊以供業務模塊使用,例:DateModule,InputModule..等。
3.服務模塊:提供一些通用型的服務。好比說http服務對httpClient二次包裝適用於項目,文件服務,配置服務等。
4.其餘模塊:應用程序中咱們會根據須要會作一些指令管道等,其就造成一個指令模塊包含應用程序中全部等指令,管道模塊包含應用程序中的全部管道。後來以爲,其實這些指令管道不須要集中起來統一導出引用。由於一個模塊並不會引用到指令模塊中超過百分之八十的指令,so 只須要把它們集中到一個pipe文件夾下,哪一個模塊須要用到具體個指令or管道,直接聲明在其模塊中使用即可。
咱們將系統根據其功能 業務劃分好模塊,有利於合做開發,代碼的維護和使用。
建立特性模塊
ng g m order // 建立訂單模塊
// ng g m order --routing //建立的訂單模塊帶路由
ng g c order/list // 訂單模塊下新建一個list 組件
咱們看最後cli給咱們生成的目錄結構
order.module.ts
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ListComponent } from './list/list.component'; @NgModule({ declarations: [ListComponent],//定義list組件 exports: [ListComponent],//導出list組件 imports: [ CommonModule ] }) export class OrderModule { }
list.component.ts
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-list', templateUrl: './list.component.html', styleUrls: ['./list.component.scss'] }) export class ListComponent implements OnInit { constructor() { } ngOnInit() { } }
導入使用特性模塊
如今咱們導入根模塊
app.module.ts
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { OrderModule } from './order/order.module'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule, OrderModule //將order模塊導入 ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
app.component.html 在跟模塊使用
<!--The content below is only a placeholder and can be replaced.--> <div style="text-align:center"> <h1> Welcome to {{ title }}! </h1> </div> <app-list></app-list> <router-outlet></router-outlet>
咱們能夠看到渲染了order模塊的list組件
若是咱們將全部的模塊都導入根模塊,那麼應用在初始化加載的時候就會很是慢。這時候咱們應該考慮使用惰性加載。根據需求加載相應都模塊,減小應用初始化包的大小以及減小加載的時間,提升用戶體驗性。
惰性加載的模塊特色是該模塊擁有路由模塊。so 接着上面咱們建立了一個訂單模塊 咱們給訂單模塊加上路由。並再建立一個user.module以及user.module模塊下的list組件。
order.module
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { OrderRoutingModule } from './order-routing.module'; import { ListComponent } from './list/list.component'; @NgModule({ declarations: [ListComponent], imports: [ CommonModule, OrderRoutingModule ] }) export class OrderModule { }
order-routing.module
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { ListComponent } from './list/list.component'; const routes: Routes = [ { path: 'list', component: ListComponent }, ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class OrderRoutingModule { }
user模塊如此類推
接下來配置路由
AppRoutingModule在頂級路由中配置
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = [ { path: 'orders', loadChildren: './order/order.module#OrderModule' }, { path: 'orders', loadChildren: './user/user.module#UserModule' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
咱們給app.component.html新增兩個button
<!--The content below is only a placeholder and can be replaced.--> <div style="text-align:center"> <h2> Welcome to {{ title }}! </h2> </div> <button routerLink="/user/list">user</button> <button routerLink="/order/list">order</button> <router-outlet></router-outlet>
效果圖
惰性加載模塊有什麼好處呢,在大型項目中每每有許多個模塊,並且大很大。若是一個模塊1m,若是咱們在瀏覽器輸入地址打開這個應用,瞬間要加載100m 是很是慢的,並且咱們並不是要是用到着這100個模塊。將系統業務拆分爲各個模塊,劃分好界限。按需加載,我點擊了user 我加載user 模塊我出現user 列表,對user進行操做。當我須要使用時才加載極大的減小了頁面初始加載的時間以及減小了資源的消耗。
共享模塊顧名思義,就是共享於全部的模塊中。首先得定義好這個模塊的具體功能特性,好比指令、管道和組件等分別封裝成一個個模塊,哪些業務模塊須要使用到其裏面的功能變導入其模塊中即可。簡單的好比,本系統的input 都是統同樣式的,咱們能夠製做一個input 模塊 而後在其餘模塊直接導入使用。這極大的規範了系統的統一性和下降了之後的維護成本。
此隨筆乃本人學習工做記錄,若有疑問歡迎在下面評論,轉載請標明出處。
若是對您有幫助請動動鼠標右下方給我來個贊,您的支持是我最大的動力。