Angular+Nest从0到1打造全栈项目

1,449 阅读5分钟

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创建一个数据库,步骤如下:

image.png

image.png


填写了连接的相关配置后,点击“确定”就拥有属于自己的数据库了。接下来需要添加以下几行代码来更新 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 请求,例如 GETPOSTPUT 和 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() 方法来配置路由器, 并把它的返回值添加到 AppModuleimports 数组中。

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 应用,最终构建出一个完整的全栈项目。在本教程中只涉及项目构建流程及基础操作,进阶用法请参照官方文档。