angular 模塊 @NgModule的使用及理解


@NgModule 的重要作用
在 Angular 中,NgModule 有以下幾個重要的作用:

NgModule 最根本的意義是幫助開發者組織業務代碼,開發者可以利用 NgModule 把關系比較緊密的組件組織到一起,這是首要的。
NgModule 用來控制組件、指令、管道等的可見性,處於同一個 NgModule 里面的組件默認互相可見,而對於外部的組件來說,只能看到 NgModule 導出( exports )的內容,這一特性非常類似 Java 里面 package 的概念。也就是說,如果你定義的 NgModule 不 exports 任何內容,那么外部使用者即使 import 了你這個模塊,也沒法使用里面定義的任何內容。


NgModule 是 @angular/cli 打包的最小單位。打包的時候,@angular/cli 會檢查所有 @NgModule 和路由配置,如果你配置了異步模塊,cli 會自動把模塊切分成獨立的 chunk(塊)。這一點是和其它框架不同的,其它框架基本上都需要你自己去配置 webpack,自己定義切分 chunck 的規則;而在 Angular 里面,打包和切分的動作是 @angular/cli 自動處理的,不需要你干預。當然,如果你感到不爽,也可以自己從頭用 webpack 配一個環境出來,因為 @angular/cli 底層也是用的 webpack。
NgModule 是 Router 進行異步加載的最小單位,Router 能加載的最小單位是模塊,而不是組件。當然,模塊里面只放一個組件是允許的,很多組件庫都是這樣做的。
場景:假設你在做一個后台管理系統,這個管理系統有多個模塊,每個模塊的業務不一樣,但是里面的組件邏輯卻有點相似。比如A module里面有一個index 組件;B module 里面也有一個index組件。這樣用module來管理各自的組件,可以保證維護者很清楚地知道這個組件組件是服務於哪個業務模塊的,即便不小心引用錯誤也會有報錯。

 

@NgModule 的使用方式
看一個最簡單的 @NgModule 的定義:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { TestViewChildComponent } from './test-view-child/test-view-child.component';
import { ChildOneComponent } from './test-view-child/child-one/child-one.component';

@NgModule({
declarations: [
AppComponent,
TestViewChildComponent,
ChildOneComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }


declarations:用來放組件、指令、管道的聲明。
imports:用來導入外部模塊。
providers:需要使用的 Service 都放在這里。
bootstrap:定義啟動組件。你可能注意到了這個配置項是一個數組,也就是說可以指定做個組件作為啟動點,但是這種用法是很罕見的。


@NgModule 的注意點
每個應用至少有一個根模塊,按照慣例,根模塊的名字一般都叫 AppModule,如果你沒有非常特別的理由,就不要隨意改這個名字了,這相當於一個國際慣例。
組件、指令、管道都必須屬於一個模塊,而且只能屬於一個模塊。
NgModule 和 ES6 里面的 Module 是完全不同的兩個概念。ES6 里面的模塊是通過 export 和 import 來進行聲明的,它們是語法層面的內容;而 NgModule 完全不是這個概念,從上面的作用列表你也能看出來。最重要的一點,目前,ES6 里面的 import 只能靜態引入模塊,並不能異步動態加載模塊,而 NgModule 可以配合 Router 來進行異步模塊加載,在后面的 Router 這一節里面會有實例代碼。
模塊的定義方式會影響依賴注入機制:對於直接 import 的同步模塊,無論你把 @Injectable 類型的組件定義在哪個模塊里面,它都是全局可見的。比如:在子模塊 post.module.ts 的 providers 數組里面定義了一個 PostListService,你可能會覺得這個 PostListService 只有在 post.module.ts 里面可見。而事實並非如此, PostListService 是全局可見的,就相當於一個全局單例。與此對應,如果你把 PostListService 定義到一個異步加載的模塊里面,它就不是全局可見的了,因為對於異步加載進來的模塊,Angular 會為它創建獨立的 DI( Dependecy Injection,依賴注入)上下文。所以,如果你想讓 PostListService 全局可見,應該把它定義在根模塊 app.module 里面。同時要特別注意,如果你希望 PostListService 是全局單例的,只能在 app.module 里面的 providers 數組里面定義一次,而不能在其它模塊里面再次定義,否則就會出現多個不同的實例。關於 DI 機制更詳細的描述請參見這里。
利用這個特性,我們通常把整個應用的service 都放在一個shareModule里面,其他模塊需要使用這些服務的時候,只需要import

shareModule就可以了,即使shareModule並沒有exports 這些service,import shareModule就可以使用這些service。而shareModule里面如果有declaration 一個組件,但是如果shareModule 沒有exports 這個組件,即使你import shareModule,也不能使用shareModule 的這個組件。

 

 

 

Angular 內核中的目錄結構
Angular 本身也是用模塊化的方式開發的,當你用 cnpm install 裝好了開發環境之后,可以打開 node_modules 目錄查看整體結構。左側第一列6個目錄比較常用,這個順序是按照我自己的理解排列的,按照常用程度從上到下。

 

 

 

 

請注意,一個目錄里面可能會放多個模塊,比如 forms 目錄里面就有 FormsModule 和 ReactiveFormsModule 兩個模塊。

Form 模塊的關鍵類結構圖如下:

 

 

 

 

 

所以使用angular的各種封裝好的組件,需要查閱的就是這個組件在哪個module里;比如NgIf和NgFor 等這些指令放在CommonModule里面,使用的時候需要:

import { CommonModule } from ‘@angular/common‘;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM