## MVC(模型-视图-控制器)
`Nest` 默认使用 `Express` 库,因此,在 `Express` 中使用 `MVC` (模型 - 视图 - 控制器)模式的每一种技术同样适用于 `Nest` 。首先,让我们使用 `CLI` 工具搭建一个简单的 `Nest` 应用程序:
```bash
$ npm i -g @nestjs/cli
$ nest new project
```
为了创建一个简单的 `MVC` 应用程序,我们必须安装一个[模板引擎](http://expressjs.com/en/guide/using-template-engines.html):
```bash
$ npm install --save hbs
```
我们决定使用 [hbs](https://github.com/pillarjs/hbs#readme) 引擎,但您可以使用任何符合您要求的内容。安装过程完成后,我们需要使用以下代码配置 `express` 实例:
> main.ts
```typescript
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.useStaticAssets(join(__dirname, '..', 'public'));
app.setBaseViewsDir(join(__dirname, '..', 'views'));
app.setViewEngine('hbs');
await app.listen(3000);
}
bootstrap();
```
我们告诉 `express`,该 `public` 目录将用于存储静态文件, `views` 将包含模板,并且 `hbs` 应使用模板引擎来呈现 `HTML` 输出。
`app.useStaticAssets` 还支持第二个参数来设置虚拟目录。
```typescript
app.useStaticAssets(join(__dirname, '..', 'public'), {
prefix: '/static',
});
```
### 模板渲染
现在,让我们在该文件夹内创建一个 `views` 目录和一个 `index.hbs` 模板。在模板内部,我们将打印从控制器传递的 `message`:
> index.hbs
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>App</title>
</head>
<body>
{{ message }}
</body>
</html>
```
然后, 打开 `app.controller` 文件, 并用以下代码替换 `root()` 方法:
> app.controller.ts
```typescript
import { Get, Controller, Render } from '@nestjs/common';
@Controller()
export class AppController {
@Get()
@Render('index')
root() {
return { message: 'Hello world!' };
}
}
```
在这个代码中,我们指定模板使用`@Render()`装饰器,同时将路径处理器方法的返回值被传递给要渲染的模板。注意,该返回值是一个包含`message`属性的对象,和我们之前创建模板中的`message`占位符对应。
在应用程序运行时,打开浏览器访问 `http://localhost:3000/` 你应该看到这个 `Hello world!` 消息。
### 动态模板渲染
如果应用程序逻辑必须动态决定要呈现哪个模板,那么我们应该使用 `@Res()`装饰器,并在路由处理程序中提供视图名,而不是在 `@Render()` 装饰器中:
> 当 `Nest` 检测到 `@Res()` 装饰器时,它将注入特定于库的响应对象。我们可以使用这个对象来动态呈现模板。在[这里](http://expressjs.com/en/api.html)了解关于响应对象 `API` 的更多信息。
> app.controller.ts
```typescript
import { Get, Controller, Render } from '@nestjs/common';
import { Response } from 'express';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
root(@Res() res: Response) {
return res.render(this.appService.getViewName(), { message: 'Hello world!' });
}
}
```
[这里](https://github.com/nestjs/nest/tree/master/sample/15-mvc)有一个可用的例子。
### Fastify
如本章所述,我们可以将任何兼容的 `HTTP` 提供程序与 `Nest` 一起使用。比如 [Fastify](https://github.com/fastify/fastify) 。为了创建具有 `fastify` 的 `MVC` 应用程序,我们必须安装以下包:
```bash
$ npm i --save fastify point-of-view handlebars
```
接下来的步骤几乎涵盖了与 `express` 库相同的内容(差别很小)。安装过程完成后,我们需要打开 `main.ts` 文件并更新其内容:
> main.ts
```typescript
import { NestFactory } from '@nestjs/core';
import { NestFastifyApplication, FastifyAdapter } from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
import { join } from 'path';
async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(AppModule, new FastifyAdapter());
app.useStaticAssets({
root: join(__dirname, '..', 'public'),
prefix: '/public/',
});
app.setViewEngine({
engine: {
handlebars: require('handlebars'),
},
templates: join(__dirname, '..', 'views'),
});
await app.listen(3000);
}
bootstrap();
```
Fastify 的`API` 略有不同,但这些方法调用背后的想法保持不变。使用 Fastify 时一个明显的需要注意的区别是传递到 `@Render()` 装饰器中的模板名称包含文件扩展名。
> app.controller.ts
```typescript
import { Get, Controller, Render } from '@nestjs/common';
@Controller()
export class AppController {
@Get()
@Render('index.hbs')
root() {
return { message: 'Hello world!' };
}
}
```
在应用程序运行时,打开浏览器并导航至 `http://localhost:3000/` 。你应该看到这个 `Hello world!` 消息。
[这里](https://github.com/nestjs/nest/tree/master/sample/17-mvc-fastify)有一个可用的例子。
- 介绍
- 概述
- 第一步
- 控制器
- 提供者
- 模块
- 中间件
- 异常过滤器
- 管道
- 守卫
- 拦截器
- 自定义装饰器
- 基础知识
- 自定义提供者
- 异步提供者
- 动态模块
- 注入作用域
- 循环依赖
- 模块参考
- 懒加载模块
- 应用上下文
- 生命周期事件
- 跨平台
- 测试
- 技术
- 数据库
- Mongo
- 配置
- 验证
- 缓存
- 序列化
- 版本控制
- 定时任务
- 队列
- 日志
- Cookies
- 事件
- 压缩
- 文件上传
- 流式处理文件
- HTTP模块
- Session(会话)
- MVC
- 性能(Fastify)
- 服务器端事件发送
- 安全
- 认证(Authentication)
- 授权(Authorization)
- 加密和散列
- Helmet
- CORS(跨域请求)
- CSRF保护
- 限速
- GraphQL
- 快速开始
- 解析器(resolvers)
- 变更(Mutations)
- 订阅(Subscriptions)
- 标量(Scalars)
- 指令(directives)
- 接口(Interfaces)
- 联合类型
- 枚举(Enums)
- 字段中间件
- 映射类型
- 插件
- 复杂性
- 扩展
- CLI插件
- 生成SDL
- 其他功能
- 联合服务
- 迁移指南
- Websocket
- 网关
- 异常过滤器
- 管道
- 守卫
- 拦截器
- 适配器
- 微服务
- 概述
- Redis
- MQTT
- NATS
- RabbitMQ
- Kafka
- gRPC
- 自定义传输器
- 异常过滤器
- 管道
- 守卫
- 拦截器
- 独立应用
- Cli
- 概述
- 工作空间
- 库
- 用法
- 脚本
- Openapi
- 介绍
- 类型和参数
- 操作
- 安全
- 映射类型
- 装饰器
- CLI插件
- 其他特性
- 迁移指南
- 秘籍
- CRUD 生成器
- 热重载
- MikroORM
- TypeORM
- Mongoose
- 序列化
- 路由模块
- Swagger
- 健康检查
- CQRS
- 文档
- Prisma
- 静态服务
- Nest Commander
- 问答
- Serverless
- HTTP 适配器
- 全局路由前缀
- 混合应用
- HTTPS 和多服务器
- 请求生命周期
- 常见错误
- 实例
- 迁移指南
- 发现
- 谁在使用Nest?