首页 > 其他分享 >Nest 核心概念:模块

Nest 核心概念:模块

时间:2023-12-12 19:34:24浏览次数:25  
标签:核心 Nest ts Module user 模块 装饰


前言

上篇文章《NestJS 扫盲篇:TypeScript 类和装饰器》中,我们介绍了 TS 中类和装饰器的用法。Nest 应用基于面向对象和面向切面开发,大量应用了类和装饰器。所以掌握这两个语法,再去学习 Nest,是一个很有必要的基础。

MVC 分层架构

在本系列更文的第一篇,较为细致的分析了 Hello World 的示例代码。它只有一个根模块,也就是 App 模块,然后使用控制器接收请求,再调用服务完成具体业务的处理,最后将结果响应给客户端,如下图所示:

Nest 核心概念:模块_Nest.js

这其实就是一个经典的 MVC 分层架构:

  • Model:业务模型层或者数据模型层,用来处理业务,是整个分层架构中最复杂的部分
  • View:视图层,就是用户界面
  • Controller:控制器层,解耦视图层和模型层,职责也很明确和简单,在 Web 应用中就是接收用户请求,调用 Model 层处理后将结果响应给视图层

Nest 核心概念:模块_Nest.js_02

在 Nest 示例代码中,主要涉及到的概念有:

  • app.controller.ts:App 控制器,对应的 MVC 中的 C 层。
  • app.service.ts:App 服务,对应 MVC 中的 M 层。
  • app.module.ts:App 模块,它负责将控制器和服务组织到一起。

你会发现,为啥没看到 View 呢?因为在 MVC 盛行的年代,前后端都是耦合在一起的,拿 Java 来说,View 层就是 JSP 。对于现在前后端分离的项目来说,View 层就是 React,Vue 等框架写的可以独立部署的页面应用。

写一个 Nest 应用,最基本的就是写模块,控制器和服务。下面就是对这三个概念的介绍。

模块

如何理解模块

首先要区分 Nest 模块和平时前端开发中经常提及的“前端模块化”中的模块。后者是属于 JS 语言层面的概念,是一种语法,比如标准的ES Module 规范中的模块就是使用 export 导出,使用 import 导入,还有 CommonJS 规范使用 module.exports 导出,使用 require 导入。

而前者是 Nest 应用层面上的概念,跟它对应的应该是前端组件化中的组件,比如 Vue 开发就是用组件组成一个完整的页面。Nest 使用模块来组织应用的结构,比如一个博客系统中,可以分为用户模块,文章模块等。

每个 Nest 应用都有一个根模块,按照约定大于配置的思想,都会定义在 app.module.ts 文件中,是一个名为 AppModule 的类。其他的模块都是它的子模块,都会被它引入,组成一个完整的应用。

Nest 核心概念:模块_Nest.js_03

模块的代码表示

Nest 模块在定义上是使用装饰器 @Module() 装饰的类,使用元数据描述一些模块的属性,用以组织该模块。

所谓元数据,就是描述数据的数据。简单理解的话,装饰器工厂接受的参数就是元数据,它们不直接参与到你的编码中,它们用来描述这个模块的组成。@Module() 装饰器接受一个描述模块属性的对象,有四个属性:

属性

描述

providers

声明一组提供者,由 Nest 容器负责实例化,在当前模块中共享

controllers

声明一组控制器,模块必选的属性

imports

导入模块的列表,这些模块导出了此模块中所需提供者

exports

由本模块提供并应在其他模块中可用的提供者的子集

看下示例,AppModule 类使用 @Module() 装饰,所以它就是一个 Nest 模块了。看下装饰器的类型声明,按住 Ctrl 键,点击 @Moudle 就可以跳转:

export declare function Module(metadata: ModuleMetadata): ClassDecorator;

可以看到,装饰器其实一个函数。而@Module是一个装饰器工厂,接收的参数就是模块元数据对象,装饰器工厂返回一个类装饰器。

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserModule } from './user/user.module';

@Module({
  // 该模块所需的其他模块。根模块需要将所有模块都导入,才能让应用正常运行。
  // 有的子模块可能依赖另一个子模块,也要通过此选项导入。
  // 一个更直观的例子,后面要用到ORM框架比如 TypeOrm,Mongoose,它们就要在此导入再使用。
  imports: [UserModule],
    
  // 模块装饰器的必填项。因为要用它处理请求,没有它,应用接收不到请求也就没有存在的意义了。
  controllers: [AppController],
    
  // 模块的提供者,就是能提供能力,供模块的其他部分使用。服务就是最常用的一种提供者.它可以写核心逻辑,操作数据库等等,然后在控制器中被使用。
  providers: [AppService],
})
export class AppModule {}


模块的组织

模块在使用装饰器声明时,需要传入一些元数据信息,比如它的控制器和提供者。

在模块的目录组织上,一个良好的风格是将该模块相关的资源放到同一个文件夹中管理,比如用户模块有控制器,服务,还有数据层的 dto 文件等等,就可以放到 user 目录下:

src
├──user
│    ├──dto
│    │   └──create-user.dto.ts
│    ├──interfaces
│    │     └──user.interface.ts 
│    ├─user.service.ts
│    ├─user.controller.ts
│    └──user.module.ts
├──app.module.ts
└──main.ts

然后,新建的目录一定要在 app.module.ts 中引入:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserModule } from './user/user.module';

@Module({
  imports: [UserModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

在《Nest 应用目录结构和脚手架命令》中介绍了常用的脚手架命令,要新建一个模块,可以直接使用 nest g module

$ nest g module user

CLI 会自动在 src 目录下新建 user 目录和对应的模块文件,之后再使用命名创建对应的控制器和服务等内容。

使用脚手架命令创建的好处是省时省力,能自动在根模块 AppModule 中注册,能自动处理控制器和服务之间的关系。

总结

本文介绍了经典的 MVC 分层架构,以及各层和 Nest 应用的对照。然后讲解了 Nest 模块的具体定义,使用 @Module 装饰器声明的类,就是模块。@Module() 接收一些信息来描述此模块的构成,主要是声明此模块所依赖的其他模块,控制器,提供者,和要导出的供其他模块所使用的部分。

下篇文章会继续讲解 Nest 控制器,它主要使用若干个装饰器用来处理请求,调用服务,最后响应数据。

感谢阅读,再会!


标签:核心,Nest,ts,Module,user,模块,装饰
From: https://blog.51cto.com/u_12382805/8790178

相关文章

  • Python——第五章:json模块
    什么是json:json模块是用于处理JSON(JavaScriptObjectNotation)数据的模块,翻译过来叫js对象简谱。JSON是一种轻量级的数据交换格式,常用于将数据在不同语言之间进行传递。我们先来看一段json代码:wf={"name":"汪峰","age":18,"hobby":"上头条","wife"......
  • 模块
     ......
  • requests模块基本使用
    1.requests模块基本使用1.1使用requests发送get请求importrequests#res响应对象,http响应,python包装成了对象,响应头,响应头。。。在res中都会有res=requests.get('https://www.cnblogs.com/Hao12345/p/17661461.html')print(res.text)#res.text------->响应体......
  • Pickle模块
    序列化:把对象转化成二进制字节反序列化:把二进制字节转化回对象Pickle模块的常见用法:Pickle.dunps  把对象(数据)转化成字节Pickle.loads  把字节转化回对象(数据)Pickle.dunp  把对象序列化成字节之后写入到文件Pickle.load  把文件中的字节反序列化成对象在Pyth......
  • 多种DC电源模块的比较和评价
    多种DC电源模块的比较和评价BOSHIDADC电源模块是一种重要的电子零件,可以将交流电转换为直流电,并为相应的电路提供所需的电能。随着技术的进步,市场上的DC电源模块种类越来越多,不同类型的DC电源模块有着不同的特点和优缺点。 1.线性稳压模块线性稳压模块是一种简单而实用的DC......
  • Pydantic模块学习
    Pydantic是一个Python库,用于数据验证和设置强类型数据结构。它是一个数据验证库,专门设计用于数据解析和验证,尤其在处理用户输入、API请求等情境中很有用。以下是Pydantic的一些主要特点和用法: 使用Pydantic主要涉及以下几个步骤:定义数据模型:创建一个继承自pydantic......
  • 造纸企业ERP包含哪些模块?造纸企业ERP有什么用
        造纸企业规模的不同,遇到的管理问题各异,有些造纸企业存在多仓库、多平台、多车间数据协同问题,还有些造纸企业内部各个业务环节信息流动速度慢,信息沟通成本较高,不同程度影响企业的车间产能和生产成本等。同期也有不少造纸企业借助ERP系统实现财务整合、随时进行多维属......
  • Livepatch模块的ELF格式要求【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/livepatch/module-elf-format.htmlLivepatch模块的ELF格式要求本文档概述了livepatch模块必须遵循的ELF格式要求。1.背景和动机以前,livepatch需要特定于体系结构的代码来编写重定位。然而,模块加载器中已经存在特定于体系结构的代码来......
  • springboot下添加日志模块和设置日志文件输出
    前言日志的使用将通过SLF4J来使用,SLF4J(SimpleLoggingFacadeforJava)是一个为Java应用提供简单日志记录的接口。它的主要目标是在不同的日志系统之间提供一个简单的抽象层,使得应用能够以一种灵活的方式切换日志实现,而不需要修改应用本身的代码。SLF4J不是一个具体的日志实现,而......
  • 前端学习笔记202310学习笔记第一百壹拾玖天-模块包-内置模块http之爬虫3
    ......