阅读 678

2020前端实践|优雅的实现一个全栈项目(二)

更新一个小的篇章,当我在选择后台的技术选型的时候,我决定尝试下完全支持的Typescript作为技术首选,尝试新的技术的同时,巩固下自己对于typescript的理解。数据据选择mysql的原因是,linux安装mongoDB要好久啊。尤其是在archlinux下。简直是太苦逼了。反正是做一个数据存储来使用。无伤大雅。这篇文章主要是带大家来入门一下Nest框架的使用方法,完成一个标准的RESTful接口的示例。如果你准备自己做后台,那么Nest不妨是一个优质的选择。

安装Nest脚手架

根据官方文档,可以通过npm来安装脚手架工具

npm install -g @ntstjs/cli
复制代码

Tip: 如果你安装失败,可以尝试使用淘宝源来进行安装 安装后,就可以使用nest的脚手架创建第一个nest.js项目了

Nest项目为什么这么吸引我

对于Nest吸引我的,第一眼就是有完整的模块化概念,数据库映射......,不得不说非常的Nce,先来说一下Nest的模型系统吧,它类似一个经典的设计概念,MVC。先来看一下官方默认基础的app模块

image.png

里面有五个文件,spec.ts和main.ts这两个先不看。我们重点放在controller,module,service上面,这三个东西分别对应的就是模型层,控制层,服务层 。

在Nest中,通常将api请求方法写在逻辑层中进行前端数据的导出,可以看下官方的Demo实例: 在app逻辑层中,抛出一个类,类里面,可以看出都是装饰器,类似spring框架,非常的优雅。@Get注释了一个方法,代表着这是一个get请求,实例中的get请求返回的是服务层的getHello方法。而在服务层中处理我们需要的数据,最后在模型层中去导出。在我们想展示的地方导入就可以。由于APP本来就是原始入口模型。所以我们写的模块都是导入到这里。

逻辑层

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

复制代码

服务层

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
 
}
复制代码

模型层

  import { Module } from '@nestjs/common';
  import { AppController } from './app.controller';
  import { AppService } from './app.service';
  import { TypeOrmModule } from '@nestjs/typeorm';
  import { UsersModule } from './users/users.module';
  import config from './config/mysql'

  @Module({
    imports: [
      TypeOrmModule.forRoot(config),
      UsersModule
    
    controllers: [AppController],
    providers: [AppService],
  })
  export class AppModule {}

复制代码

实战一个RESTful接口

就拿项目的用户模块来做一个实例,来实现一个简单的接口吧。

安装mysql

如何安装mysql,不需要在这里写吧。三大系统百度一下方案百花齐放,安装完成后,创建你项目的数据库 后进行下一步。

使用如下命令创建一个名称为test的项目

nest new test 并且创建如下文件

image.png
你也可以使用自带的命令来创建逻辑层和模型层

// 创建逻辑层
nest g controller users
//创建服务层
nest g service users/users
//创建模型层
nest g module users
复制代码

连接Mysql,并创建数据库映射

使用如下命令安装数据库的基本库包

@nestjs/typeorm typeorm mysql
复制代码

连接数据库

在appModule中配置数据库

imports: [
  // config对象,可以在这里直接写,也可以分一个模块
	TypeOrmModule.forRoot(config)
],
复制代码

config 对象 将其填写到上面的foRoot中就好了。其中User为你创建的User映射类的导出引入

{
	type: 'mysql', // 数据库
	host: 'localhost', // host
	port: 3306, // 端口
	username: 'root', //用户名
	password: '******', // 密码
	database: 'visual', // 你创建的数据库容器
	timezone: 'UTC', // 时区
	charset: 'utf8mb4', // 编码
  entities: [User], // 映射模型bean类
	multipleStatements: true,
	dropSchema: false,
	synchronize: true,
	logging: true
}
复制代码

创建user数据库映射模型

使用@Entity()装饰你的User类
@PrimaryGeneratedColumn() = 主键列字段 @Columan() = 列字段

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
import { ApiProperty } from '@nestjs/swagger';

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  @ApiProperty({ description: 'id' })
  id: number;

  @Columan()
  @ApiProperty({ description: '账号' })
  user: string;

  @Column()
  @ApiProperty({ description: '姓名' })
  name: string;

  @Column()
  @ApiProperty({ description: '密码' })
  password: string;
}
复制代码

编写模型层

在模型中,我们配置引入服务层和逻辑层。以及数据映射模型,代码如下

import { TypeOrmModule } from '@nestjs/typeorm';
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { User } from './user.db';
import { UsersService } from './users.service'

@Module({
  imports: [TypeOrmModule.forFeature([User])],  // 引入数据模型
  providers: [UsersService], // 注入服务
  controllers: [UsersController] // 注册控制层
})
export class UsersModule {}

复制代码

编写服务层

这里我用来写入数据库数据的操作方法逻辑,代码如下:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.db'

@Injectable()
export class UsersService {
  // 接收注入
  constructor(
    @InjectRepository(User)
    private readonly usersRepository: Repository<User>
  ) {}
  
  // 查询全部。返回一个User数组
  findAll(): Promise<User[]> {
    return this.usersRepository.find();
  }
  
  // 根据ID查询
  findOne(id: string): Promise<User> {
    return this.usersRepository.findOne(id);
  }
  
  // 根据 ID删除
  async remove(id: string): Promise<void> {
    await this.usersRepository.delete(id);
  }
  
  // 创建
  async create(params: User): Promise<void> {
    await this.usersRepository.save(params)
  }
}
复制代码

编写逻辑层

逻辑层中处理发送请求url的参数 获取和一些常用的逻辑。并返回数据结构渲染后接口数据

import { Controller, Get, Post, Body, Delete, Param, Put } from '@nestjs/common';
import { UsersService } from './users.service';
import { User } from './user.db';
import { ApiTags } from '@nestjs/swagger';

@Controller('users')
@ApiTags('用户')
export class UsersController {
  // 将服务层初始化
  constructor(private readonly usersService: UsersService) {}

  // POST创建
  @Post(['user', 'name', 'password'])
  add(@Body() bodys: User) {
    return this.usersService.create(bodys)
  }
  
  // PUT方法
  @Put(':id')
  update(){}
  
  // Delete方法
  @Delete(':id') 
  deleteUser(@Param('id') id: string) {
    return this.usersService.remove(id)
  }
  // Get方法
  @Get(':id')
  find(@Param('id') id: string) {
    // return this.usersService.findOne(id)
    return this.usersService.findAll()
  }
}

复制代码

添加Swagger文档

添加Swagger来修饰API接口,更加的直观。使用npm安装包

npm install --save @nestjs/swagger swagger-ui-express
复制代码

在main.ts中使用

const options = new DocumentBuilder()
    .setTitle('标题')
    .setDescription('描述')
    .setVersion('版本')
    .addTag('标签')
    .build();
const document = SwaggerModule.createDocument(app, options);
复制代码

image.png

总结

这是一篇基础的文章,因为我也是刚刚尝试这个技术,发出来作为服务端的启程,前端项目也在构思怎么去做的更好,慢慢的开阔分支。当作对自己2020年的一个小目标,与君共勉。如果觉得不错,可以给我一个小手哦。

上一篇文章地址:2020前端实践|优雅的实现一个全栈项目(一)

线上版本: 不知名后台管理系统

Github: 项目源码+日常更新中

image.png