Angular 從入坑到挖坑 - 模組簡介
阿新 • • 發佈:2020-06-28
### 一、Overview
Angular 入坑記錄的筆記第七篇,介紹 Angular 中的模組的相關概念,瞭解相關的使用場景,以及知曉如何通過特性模組來組織我們的 Angular 應用
對應官方文件地址:
- [NgModule 簡介](https://angular.cn/guide/architecture-modules)
- [NgModules](https://angular.cn/guide/ngmodules)
- [JavaScript 模組 vs. NgModule](https://angular.cn/guide/ngmodule-vs-jsmodule)
- [使用根模組啟動應用](https://angular.cn/guide/bootstrapping)
- [常用模組](https://angular.cn/guide/frequent-ngmodules)
- [特性模組](https://angular.cn/guide/feature-modules)
### 二、Contents
1. [Angular 從入坑到棄坑 - Angular 使用入門](https://www.cnblogs.com/danvic712/p/getting-started-with-angular.html)
2. [Angular 從入坑到挖坑 - 元件食用指南](https://www.cnblogs.com/danvic712/p/angular-components-guide.html)
3. [Angular 從入坑到挖坑 - 表單控制元件概覽](https://www.cnblogs.com/danvic712/p/angular-forms-overview.html)
4. [Angular 從入坑到挖坑 - HTTP 請求概覽](https://www.cnblogs.com/danvic712/p/angular-http-guide.html)
5. [Angular 從入坑到挖坑 - Router 路由使用入門指北](https://www.cnblogs.com/danvic712/p/getting-started-with-angular-routing.html)
6. [Angular 從入坑到挖坑 - 路由守衛連連看](https://www.cnblogs.com/danvic712/p/getting-started-with-angular-route-guards.html)
7. [Angular 從入坑到挖坑 - 模組簡介](https://www.cnblogs.com/danvic712/p/angular-modules-introduction.html)
### 三、Knowledge Graph
![思維導圖](https://img2020.cnblogs.com/blog/1310859/202006/1310859-20200627104310636-274881381.png)
### 四、Step by Step
#### 4.1、前端模組化
前端模組化是指將程式中一組相關的功能按照一定的規則組織在一塊,整個模組內部的資料和功能實現是私有的,通過 export 暴露其中的一些介面(方法)與系統中的別的模組進行通訊
##### NgModule 簡介
在 Angular 應用中,至少會存在一個 NgModule,也就是應用的根模組(AppModule),通過引導這個根模組就可以啟動整個專案
像開發中使用到 FormsModule、HttpClientModule 這種 Angular 內建的庫也都是一個個的 NgModule,在開發中通過將元件、指令、管道、服務或其它的程式碼檔案聚合成一個內聚的功能塊,專注於系統的某個功能模組
##### 常見的 NgModule 模組
| 模組名稱 | 模組所在檔案 | 功能點 |
| ------------------------------------------------------------ | ---------------------------------------------------------- | ------------------------------------ |
| [BrowserModule](https://angular.cn/api/platform-browser/BrowserModule) | @angular/platform-browser | 用於啟動和執行瀏覽器應用的的基本服務 |
| [CommonModule](https://angular.cn/api/common/CommonModule) | @angular/common | 使用 NgIf、NgFor 之類的內建指令 |
| [FormsModule](https://angular.cn/api/forms/FormsModule) | @angular/forms | 使用 NgModel 構建模板驅動表單 |
| [ReactiveFormsModule](https://angular.cn/api/forms/ReactiveFormsModule) | @angular/forms | 構建響應式表單 |
| [RouterModule](https://angular.cn/api/router/RouterModule) | @angular/router | 使用前端路由 |
| [HttpClientModule](https://angular.cn/api/common/http/HttpClientModule) | @angular/common/[http](https://angular.cn/api/common/http) | 發起 http 請求 |
##### JavaScript 模組與 NgModule
在 JavaScript 中,每一個 js 檔案就是一個模組,檔案中定義的所有物件都從屬於那個模組。 通過 `export` 關鍵字,模組可以把其中的某些物件宣告為公共的,從而其它 JavaScript 模組可以使用 `import ` 語句來訪問這些公共物件
例如下面的示例程式碼中,別的 javascript 模組可以通過匯入這個 js 檔案來直接使用暴露的 `getRoles` 和 `getUserInfo` 方法
```javascript
function getRoles() {
// ...
}
function getUserInfo() {
// ...
}
export {
getRoles,
getUserInfo
}
```
NgModule 是一個帶有 @NgModule 裝飾器的類,通過函式的引數來描述這個模組,例如在上節筆記中建立的 CrisisModule,定義了我們在該特性模組中建立的元件,以及需要使用到的其它模組
![NgModule](https://img2020.cnblogs.com/blog/1310859/202006/1310859-20200627104325142-1402701227.png)
在使用 @NgModule 裝飾器時,通常會使用到下面的屬性來定義一個模組
- declarations:當前模組中的元件、指令、管道
- imports:當前模組所需的其它 NgModule 模組
- exports:其它模組中可以使用到當前模組可宣告的物件
- providers:當前模組向當前應用中其它應用模組暴露的服務
- bootstrap:用來定義整個應用的根元件,是應用中所有其它檢視的宿主,只有根模組中才會存在
#### 4.2、應用的根模組
根模組是用來啟動此 Angular 應用的模組, 按照慣例,它通常命名為 `AppModule`
通過 Angular CLI 新建一個應用後,預設的根模組程式碼如下,通過使用 @NgModule 裝飾器裝飾 AppModule 類,定義了這個模組的一些屬性特徵,從而告訴 Angular 如何編譯和啟動本應用
```typescript
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 { }
```
##### declarations
`declarations` 陣列告訴 Angular 哪些元件屬於當前模組。 當建立新的元件時,需要將它們新增到 `declarations` 陣列中。每個元件都只能宣告在一個 `NgModule` 類中,同時,如果你使用了未宣告過的元件,Angular 將會報錯
同樣的,對於當前模組使用到的自定義指令、自定義管道,也需要在 `declarations` 陣列中進行宣告
##### imports
`imports` 陣列表明當前模組正常工作時需要引入哪些的模組,例如這裡使用到的 `BrowserModule`、`AppRoutingModule` 或者是我們使用雙向資料繫結時使用到的 `FormsModule`,它表現出當前模組的一個依賴關係
##### providers
`providers` 陣列定義了當前模組可以提供給當前應用其它模組的各項服務,例如一個使用者模組,提供了獲取當前登入使用者資訊的服務,因為應用中的其它地方也會存在呼叫的可能,因此,可以通過新增到 `providers` 陣列中,提供給別的模組使用
##### bootstrap
Angular 應用通過引導根模組來啟動的,因為會涉及到構建元件樹,形成實際的 DOM,因此需要在 `bootstrap` 陣列中新增根元件用來作為元件樹的根
#### 4.3、特性模組
特性模組是用來將特定的功能或具有相關特性的程式碼從其它程式碼中分離出來,聚焦於特定應用需求。特性模組通過它提供的服務以及共享出的元件、指令和管道來與根模組和其它模組合作
在上一章中,定義了一個 CrisisModule 用來包括包含與危機有關的功能模組,建立特性模組時可以通過 Angular CLI 命令列進行建立
```powershell
-- 建立名為 xxx 的特性模組
ng new component xxx
```
```typescript
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CrisisRoutingModule } from './crisis-routing.module';
import { FormsModule } from '@angular/forms';
import { CrisisListComponent } from './crisis-list/crisis-list.component';
import { CrisisDetailComponent } from './crisis-detail/crisis-detail.component';
@NgModule({
declarations: [
CrisisListComponent,
CrisisDetailComponent
],
imports: [
CommonModule,
FormsModule,
CrisisRoutingModule
]
})
export class CrisisModule { }
```
當建立完成後,為了將該特性模組包含到應用中,需要和 `BrowserModule`、`AppRoutingModule` 一樣,在根模組中 imports 引入
預設情況下,NgModule 都是急性載入的,也就是說它會在應用載入時儘快載入,所有模組都是如此,無論是否立即要用。對於帶有很多路由的大型應用,考慮使用惰性載入的模式。惰性載入可以減小初始包的尺寸,從而減少程式首次的載入時間
```typescript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
// 新增自定義的模組
import { CrisisModule } from './crisis/crisis.module';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
CrisisModule, // 引入自定義模組
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
```