Angular+Nest从零到一打造全栈项目
1. 介绍
要打造一个完整的前后端项目,必须要有趁手的工具,这里用到的前台框架是Angular,Angular 是一个应用设计框架与开发平台,用于创建高效、复杂、精致的单页面应用。后台使用nest以及TypeORM进行数据管理及操作。Nest.js 是一个可扩展的服务端 JavaScript 框架,默认选择Express作为底层服务框架。首先,我们将使用 Nest.js 来构建 RESTful 后端 API;然后使用 Angular 来构建前端。其中前后端的应用将在不同的端口上运行,并将作为独立的域运行。
2. 安装
安装脚手架前请确保在本地安装 Node.js(至少 v12 版本)和 npm(至少 v6 版本)。Node.js 是一个允许在浏览器之外运行 JavaScript 代码的运行环境。它带有一个名为 npm的预安装的包管理工具,可安装和更新软件包。
2.1 Angular安装
npm i -g @angular/cli
创建一个Angular项目:ng new my-frontend
2.2 Nest安装及其他依赖
npm i -g @nestjs/cli
安装swagger:npm i swagger-ui-express --save
安装typeORM:npm i typeorm --save
相关依赖:npm i reflect-metadata --save
安装PostgreSQL数据库:npm i pg --save
创建一个nest项目:nest new my-backend
3. 数据库配置
这一步, 我们将配置PG数据库 并将其集成到 Nest.js 应用中,用 PG 存储应用的数据。首先使用Navicat创建一个数据库,步骤如下:
填写了连接的相关配置后,点击“确定”就拥有属于自己的数据库了。接下来需要添加以下几行代码来更新 app.module.ts中的内容:
~/blog-backend/src/app.module.ts
const options: ConnectionOptions = {
type: "postgres",
host:"localhost",
port: 3306,
username: "postgres",
password: "postgres",
database: "pg",
synchronize: false,
}
@Module({
imports: [
TypeOrmModule.forRoot({
...options,
entities:[],
logging: ["error", "info", "log", "migration","query","schema", "warn"],
}),
HttpModule,
],
controllers:[],
providers: [],
})
在这个文件中,我们使用 forRoot()
方法来完成与数据库的连接。完成编辑后,保存并关闭文件。
4. 创建数据模型
接下来我们就可以管理及组织数据了,首先需要给数据做一个模型,所有的数据按照模型的结构进行创建,在项目中创建一个model文件夹,专门存放数据的模型,模型示例如下:
@Entity("result")
export class ResultEntity {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column({ nullable: true })
name?: string;
@Column()
count: number = 1;
@CreateDateColumn()
createTime?: Date;
@UpdateDateColumn()
updateTime?: Date;
@VersionColumn()
version?: number;
}
这样我们就创建好了一个数据模型,有了数据就可以使用nest的相关模块。
5.创建控制器(Controller)和服务(Service)
5.1 服务
服务(在 Nest.js 中也称它为 provider)的意义在于从仅应处理 HTTP 请求的控制器中移除业务逻辑,并会将更复杂的任务重定向到其他的服务类。服务是普通的 JavaScript 类,在它们的代码上方会带有 @Injectable()
装饰器。要生成新服务,请在该项目目录下终端运行以下命令:nest generate service result
。通过nest命令创建了一个新的result.service.ts文件,负责与数据库交互,并将合适的响应返回给控制器。
~/my-backend/src/result.service.ts
import { Injectable } from "@nestjs/common";
import { LinqRepository } from "typeorm-linq-repository";
import { InjectRepository } from "@nestjs/typeorm";
import { ResultEntity } from "../models/result";
@Injectable()
export class ResultService{
linqRepo:LinqRepository<ResultEntity>=new LinqRepository(ResultEntity);
constructor(
@InjectRepository(ResultEntity)
){
}
async add( result:ResultEntity){
await this.linqRepo.upsert(result);
}
}
5.2 控制器
在 Nest.js 中,控制器负责处理来自应用客户端的任何请求并返回适当的响应。与大多数其他 web 框架类似,对于应用而言重要的就是监听请求并响应。利用 nest
命令生成一个新的控制器文件:nest generate controller mycontroller
Nest.js 中的控制器是用 @Controller
元数据装饰的 TypeScript 文件,并生成了必要的方法来处理来自客户端的 HTTP 请求,例如 GET
、POST
、PUT
和 DELETE
。简单的例子如下:
~/my-backend/src/mycontroller.controller.ts
import { Controller, Get, Post, Body, Param } from "@nestjs/common";
import { ApiTags, ApiOperation } from "@nestjs/swagger";
import { ResultEntity } from "../../models/result";
import { ResultService } from "../../result.service";
@ApiTags('示例数据')
@Controller("Result")
export class ResultController {
constructor(
private readonly resultService: ResultService
)
{
}
@ApiOperation({ summary: "添加数据", description: "" })
@Post("addOrUpdate")
async add(@Body() resultEntity:ResultEntity)
{
await this.resultService.add(resultEntity);
}
6.创建前端组件及路由
我们把设计好的页面拆分成多个区域,每个区域作为一个独立的组件引入,使用ng
命令创建一个组件:ng g c my-component
。在这个组件中由三部分构成:HTML、CSS、TypeScript。HTML页面中编写组件的页面代码,CSS为相关的样式表,TS处理组件的逻辑。这里涉及到比较多angular的语法点,比如模板语法、父子组件传值、管道以及RXJS,详细用法挪步官方文档。
Angular 的路由器能让用户从一个视图导航到另一个视图。每个带路由的 Angular 应用都有一个Router服务的单例对象。 当浏览器的 URL 变化时,路由器会查找对应的 Route,并据此决定该显示哪个组件。路由器需要先配置才会有路由信息。 下面的例子创建了五个路由定义,并用 RouterModule.forRoot()
方法来配置路由器, 并把它的返回值添加到 AppModule
的 imports
数组中。
const routes: Routes = [
{ path: '', redirectTo: "base", pathMatch: "full" },
{
path: 'home', component: HomeComponent
},
{
path: 'data', component: DataComponent
},
{
path: 'organization', component: OrganizationComponent, children:
[
{ path: '', redirectTo: "base1", pathMatch: "full" },
{
path: 'base1', component: BaseInfoComponent
},
]
},
];
@NgModule({
imports: [RouterModule.forRoot(routes,
{
scrollPositionRestoration: 'enabled',
anchorScrolling: 'enabled',
onSameUrlNavigation: 'reload',
useHash: true
}),
],
exports: [RouterModule]
})
export class AppRoutingModule { }
这样我们就创建好了基本的组件以及路由跳转,常见的还有service注入服务,将一些公共数据及函数存储在service中方便各组件公用。
最后同时启动前后台项目,就可以实时操作项目的数据及界面,并利用swagger调试后台的接口。
7.总结
在本教程中通过使用 Nest.js 构建后端 RESTful API,使用 Angular处理所有前端逻辑。此外,还将 PG 数据库集成到 Nest.js 应用,最终构建出一个完整的全栈项目。在本教程中只涉及项目构建流程及基础操作,进阶用法请参照官方文档。