Nest入門教程 - 模塊
模塊
模塊是具有 @Module()
裝飾器的類。 @Module()
裝飾器提供了元數據,Nest 用它來組織應用程序結構。
每個 Nest 應用程序至少有一個模塊,即根模塊。根模塊是 Nest 開始安排應用程序樹的地方。事實上,根模塊可能是應用程序中唯一的模塊,特別是當應用程序很小時,但是對於大型程序來說這是沒有意義的。在大多數情況下,您將擁有多個模塊,每個模塊都有一組緊密相關的功能。
@module()
裝飾器接受一個描述模塊屬性的對象:
providers | 由 Nest 注入器實例化的提供者,並且可以至少在整個模塊中共享 |
controllers | 必須創建的一組控制器 |
imports | 導入模塊的列表,這些模塊導出了此模塊中所需提供者 |
exports | 由本模塊提供並應在其他模塊中可用的提供者的子集。 |
默認情況下, 模塊封裝提供者。這意味着如果提供者即不是當前模塊的一部分, 也不是從另外模塊(已導入)導出的,那麼它就是無法注入的。
功能模塊
CatsController
和 CatsService
屬於同一個應用程序域。 應該考慮將它們移動到一個功能模塊下,即 CatsModule
。
cats/cats.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
@Module({
controllers: [CatsController],
providers: [CatsService],
})
export class CatsModule {}
Copy to clipboardErrorCopied
要使用 CLI 創建模塊,只需執行 $ nest g module cats
命令。
我已經創建了 cats.module.ts
文件,並把與這個模塊相關的所有東西都移到了 cats 目錄下。我們需要做的最後一件事是將這個模塊導入根模塊 (ApplicationModule)
。
app.module.ts
import { Module } from '@nestjs/common';
import { CatsModule } from './cats/cats.module';
@Module({
imports: [CatsModule],
})
export class ApplicationModule {}
Copy to clipboardErrorCopied
現在 Nest 知道除了 ApplicationModule
之外,註冊 CatsModule
也是非常重要的。 這就是我們現在的目錄結構:
src
├──cats
│ ├──dto
│ │ └──create-cat.dto.ts
│ ├──interfaces
│ │ └──cat.interface.ts
│ ├─cats.service.ts
│ ├─cats.controller.ts
│ └──cats.module.ts
├──app.module.ts
└──main.ts
Copy to clipboardErrorCopied
共享模塊
在 Nest 中,默認情況下,模塊是單例,因此您可以輕鬆地在多個模塊之間共享同一個提供者實例。
實際上,每個模塊都是一個共享模塊。一旦創建就能被任意模塊重複使用。假設我們將在幾個模塊之間共享 CatsService
實例。 我們需要把 CatsService
放到 exports
數組中,如下所示:
cats.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
@Module({
controllers: [CatsController],
providers: [CatsService],
exports: [CatsService]
})
export class CatsModule {}
Copy to clipboardErrorCopied
現在,每個導入 CatsModule
的模塊都可以訪問 CatsService
,並且它們將共享相同的 CatsService
實例。
模塊導出
模塊可以導出他們的內部提供者。 而且,他們可以再導出自己導入的模塊。
@Module({
imports: [CommonModule],
exports: [CommonModule],
})
export class CoreModule {}
Copy to clipboardErrorCopied
依賴注入
提供者也可以注入到模塊(類)中(例如,用於配置目的):
cats.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
@Module({
controllers: [CatsController],
providers: [CatsService],
})
export class CatsModule {
constructor(private readonly catsService: CatsService) {}
}
Copy to clipboardErrorCopied
但是,由於循環依賴性,模塊類不能注入到提供者中。
全局模塊
如果你不得不在任何地方導入相同的模塊,那可能很煩人。在 Angular 中,提供者是在全局範圍內註冊的。一旦定義,他們到處可用。另一方面,Nest 將提供者封裝在模塊範圍內。您無法在其他地方使用模塊的提供者而不導入他們。但是有時候,你可能只想提供一組隨時可用的東西 - 例如:helper,數據庫連接等等。這就是爲什麼你能夠使模塊成爲全局模塊。
import { Module, Global } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
@Global()
@Module({
controllers: [CatsController],
providers: [CatsService],
exports: [CatsService],
})
export class CatsModule {}
Copy to clipboardErrorCopied
@Global
裝飾器使模塊成爲全局作用域。 全局模塊應該只註冊一次,最好由根或核心模塊註冊。 在上面的例子中,CatsService
組件將無處不在,而想要使用 CatsService
的模塊則不需要在 imports
數組中導入 CatsModule
。
使一切全局化並不是一個好的解決方案。 全局模塊可用於減少必要模板文件的數量。 imports
數組仍然是使模塊 API 透明的最佳方式。
動態模塊
Nest
模塊系統帶有一個稱爲動態模塊的功能。 它使您能夠毫不費力地創建可定製的模塊。 讓我們來看看 DatabaseModule
:
import { Module, DynamicModule } from '@nestjs/common';
import { createDatabaseProviders } from './database.providers';
import { Connection } from './connection.provider';
@Module({
providers: [Connection],
})
export class DatabaseModule {
static forRoot(entities = [], options?): DynamicModule {
const providers = createDatabaseProviders(options, entities);
return {
module: DatabaseModule,
providers: providers,
exports: providers,
};
}
}
Copy to clipboardErrorCopied
forRoot()
可以同步或異步(Promise
)返回動態模塊。
此模塊默認定義了 Connection
提供者,但另外 - 根據傳遞的 options
和 entities
- 創建一個提供者集合,例如存儲庫。實際上,動態模塊擴展了模塊元數據。當您需要動態註冊組件時,這個實質特性非常有用。然後你可以通過以下方式導入 DatabaseModule
:
import { Module } from '@nestjs/common';
import { DatabaseModule } from './database/database.module';
import { User } from './users/entities/user.entity';
@Module({
imports: [DatabaseModule.forRoot([User])],
})
export class ApplicationModule {}
Copy to clipboardErrorCopied
爲了導出動態模塊,可以省略函數調用部分:
import { Module } from '@nestjs/common';
import { DatabaseModule } from './database/database.module';
import { User } from './users/entities/user.entity';
@Module({
imports: [DatabaseModule.forRoot([User])],
exports: [DatabaseModule],
})
export class ApplicationModule {}
Copy to clipboardErrorCopied
譯者署名
用戶名 | 頭像 | 職能 | 簽名 |
---|---|---|---|
@zuohuadong | 翻譯 | 專注於 caddy 和 nest,@zuohuadong at Github | |
@Armor | 翻譯 | 專注於 Java 和 Nest,@Armor | |
@Drixn | 翻譯 | 專注於 nginx 和 C++,@Drixn | |
@tangkai | 翻譯 | 專注於 React,@tangkai | |
@havef | 校正 | 數據分析、機器學習、TS/JS技術棧 @havef |