模块
模块是用@Module()
装饰器注释的类。的@Module()
装饰提供了元数据, Nest利用它来组织应用程序结构
。
![](https://docs.nestjs.com/assets/Modules_1.png)
每个应用程序至少有一个模块,一个根模块。根模块是Nest用来构建应用程序图的起点。实际上,根模块可能是应用程序中唯一的模块,尤其是当应用程序很小时。然而,对于大型应用程序,它没有意义。在大多数情况下,您将拥有多个模块,每个模块封装一组紧密相关的功能。
所述@Module()
装饰采用单个对象,其属性描述该模块:
providers | 将由Nest注入器实例化的提供程序,并且至少可以在此模块上共享。 |
---|---|
controllers | 必须创建的控制器集 |
imports | 导出此模块中所需的提供程序的导入模块列表 |
exports | 其子集providers由此模块提供,并且应该在其他模块中可用 |
默认情况下,该模块封装提供程序。这意味着不可能注入既不是当前模块的直接组成部分,也不是从导入的模块导出的提供程序。因此,您可以将模块中导出的提供者视为模块的公共接口或API。
功能模块
在CatsController
与CatsService
属于同一应用程序域。由于它们密切相关,因此将它们移入功能模块是有意义的。功能模块仅组织与特定功能相关的代码,使代码井井有条,并建立清晰的边界。这有助于我们管理复杂性并按照SOLID原则进行开发,尤其是随着应用程序和/或团队规模的增长。
cats/ cats.module.ts
JS
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
@Module({
controllers: [CatsController],
providers: [CatsService],
})
export class CatsModule {}
提示要使用CLI创建模块,只需执行
$ nest g module cats
命令即可。
我们定义了cats.module.ts
文件,然后将与此模块相关的所有内容移动到cats
目录中。我们需要做的最后一件事是将此模块导入根模块(ApplicationModule
)。
app.module.ts
JS
import { Module } from '@nestjs/common';
import { CatsModule } from './cats/cats.module';
@Module({
imports: [CatsModule],
})
export class ApplicationModule {}
这就是我们的目录结构现在的样子:
![](https://ask.qcloudimg.com/http-save/yehe-4354475/hrb3m5cxz4.png)
Cat
DTO
create-cat.dto.ts
接口
cat.interface.ts
cats.service.ts
cats.controller.ts
cats.module.ts
app.module.ts
main.ts
共享模块
在Nest中,默认情况下模块是单例,因此您可以毫不费力地在多个模块之间共享任何提供程序的相同实例。
![](https://docs.nestjs.com/assets/Shared_Module_1.png)
事实上,每个模块都是一个共享模块。一旦创建,它可以被任何模块重用。让我们想象一下,我们希望CatsService
在其他几个模块之间共享实例。为了做到这一点,我们首先需要导出CatsService
通过将其添加到模块的供应商exports
阵列,如下图所示:
cats.module.ts
JS
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 {}
现在,任何导入的模块CatsModule
都可以访问,并将CatsService
与导入该模块的所有其他模块共享同一实例。
模块重新导出
如上所述,模块可以导出其内部提供程序。而且,他们可以重新导出自己导入的模块。在下面的示例中,CommonModule
既导入和从导出的CoreModule
,使得它可用于其中导入其它模块。
JS
@Module({
imports: [CommonModule],
exports: [CommonModule],
})
export class CoreModule {}
依赖注入
模块类也可以注入提供者(例如,用于配置目的):
cats.module.ts
JS
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) {}
}
但是,由于循环依赖性,提供程序无法注入模块类。
全局模块
如果你必须在任何地方导入相同的模块集,那可能会很烦人。在Angular中,providers
它们在全局范围内注册。一旦定义,它们随处可用。另一方面,Nest将提供程序封装在模块范围内。您无法在不导入模块提供程序的情况下使用模块提供程序。但有时候,您可能只想提供一组应该始终可用的东西 - 开箱即用,例如:帮助程序,数据库连接等等。这就是为什么你能够使模块成为全局模块的原因。
JS
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 {}
该@Global()
装饰使得模块全局范围。全局模块只能注册一次,最好是根模块或核心模块之后,CatsService
提供商将无处不在,但CatsModule
不会被导入。
提示让一切都变得全局化并不是一个好的决定。全局模块可用于减少必要的样板量。该
imports
阵列仍然是使模块API透明的最佳方法。
动态模块
Nest模块系统包括一个称为动态模块的强大功能。使用此功能,您可以轻松创建可自定义的模块,这些模块可以动态注册和配置提供程序。动态模块在这里进行了广泛的介绍。在本章中,我们将简要概述以完成对模块的介绍。
以下是的动态模块定义示例DatabaseModule
:
JS
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,
};
}
}
提示的
forRoot()
可能返回动态模块同步或异步(Promise
)。
此模块Connection
默认情况下(在@Module()
装饰器元数据中)定义了提供程序,但此外-根据传递给该方法的entities
和options
对象forRoot()
,还公开了提供程序的集合,例如存储库。请注意,动态模块返回的属性扩展(而不是覆盖)@Module()
装饰器中定义的基本模块元数据。这就是从模块中导出静态声明的Connection
提供程序和动态生成的存储库提供程序的方式。
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 {}
为了导出动态模块,可以省略函数调用部分:
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 {}
本文档系腾讯云开发者社区成员共同维护,如有问题请联系 cloudcommunity@tencent.com