NestJs 学习(二) todoList应用

实现一个 TodoList 应用

  • UI实现

UI实现

  • 项目解析

项目解析

  • config 异常,管道,中间件,过滤器 使用
  • todo 主要实现todolist的增删改查
  • app.module.ts 组织应用程序结构
  • main.ts 项目配置文件,监听端口

实现

创建文件

在 cli 项目的基础上,创建todo 文件夹,如上,创建一些文件,可以手动创建,当然,也可以使用nest的命令。
generate(简写:g) 生成文件

  • class (简写: cl) 类
  • controller (简写: co) 控制器
  • decorator (简写: d) 装饰器
  • exception (简写: e) 异常捕获
  • filter (简写: f) 过滤器
  • gateway (简写: ga) 网关
  • guard (简写: gu) 守卫
  • interceptor (简写: i) 拦截器
  • middleware (简写: mi) 中间件
  • module (简写: mo) 模块
  • pipe (简写: pi) 管道
  • provider (简写: pr) 供应商
  • service (简写: s) 服务

创建一个users服务文件

$ nest generate service users
OR
$ nest g s users

注意:

  • 必须在项目根目录下创建,(默认创建在src/)。(不能在当前文件夹里面创建,不然会自动生成xxx/src/xxx。吐槽:这个没有Angular-cli智能)
  • 需要优先新建模块,不然创建的非模块以外的服务,控制器等就会自动注入更新到上级的模块里面
引入相关

既然是后端服务,那当然是要连接数据库了。我们使用 mysql数据库,然后使用typeorm来操作数据库,nest中有内置相关类 @nest/typeorm

$ npm install --save @nestjs/typeorm typeorm mysql

两种方式 引入

  • 将其 TypeOrmModule 导入到根目录中 ApplicationModule

app.module.ts

   import { Module } from '@nestjs/common';
   import { TypeOrmModule } from '@nestjs/typeorm';
   
   @Module({
     imports: [
       TypeOrmModule.forRoot({
         type: 'mysql',
         host: 'localhost',
         port: 3306,
         username: 'root',
         password: 'root',
         database: 'test',
         entities: [__dirname + '/../**/*.entity{.ts,.js}'],
         synchronize: true,
       }),
     ],
   })
   export class ApplicationModule {}
  • 在项目根目录中创建一个 ormconfig.json 文件,会自动识别

ormconfig.json

 {
   "type": "mysql",
   "host": "localhost",
   "port": 3306,
   "username": "root",
   "password": "root",
   "database": "test",
   "entities": ["src/**/**.entity{.ts,.js}"],
   "synchronize": true
 }

app.module.ts

  import { Module } from '@nestjs/common';
  import { TypeOrmModule } from '@nestjs/typeorm';
  
  @Module({
    imports: [TypeOrmModule.forRoot()],
  })
  export class ApplicationModule {}
业务逻辑

我们想要实现的是一个 todoList 主要操作有 增删改查

设计数据库

在上面的ormconfig.jsondatabase: test 是表示 所要连接的数据库。是需要本地先新建好的。如果没有,就会报错。推荐使用 Navicat 可视化数据库表,更好操作。

还有,本地数据库的 用户名,密码都是要在上面设置好的,要统一。

然后新建一个实体,运行之后会在 test 数据库中 生成一个相关的表

todo.entity.ts

 import {Column, Entity, PrimaryGeneratedColumn} from "typeorm";

 @Entity("t_todo")
 export class t_todo {
 
     // 主键 id
     @PrimaryGeneratedColumn({
         type:"bigint", 
         name:"id"
         })
     id:number;
         
     // summary
     @Column("varchar",{ 
         nullable:true,
         length:200,
         name:"summary"
         })
     // 这个字段就是输出给前端时的字段,在这里就可以写成 驼峰式的
     summary:string | null;
 
     // details
     @Column("text",{ 
         nullable:true,
         name:"details"
         })
     details:string | null;
 
     // 是否已完成
     @Column("int",{ 
         nullable:true,
         name:"is_finished"
         })
     is_finished:number | null;
 
     // 是否已删除
     @Column("int",{ 
         nullable:true,
         name:"is_del"
         })
     is_del:number | null;
 
     // 创建时间
     @Column("timestamp",{ 
         nullable:true,
         default: () => "CURRENT_TIMESTAMP",
         name:"create_time"
         })
     createTime:Date | null;
         
     // 更新时间
     @Column("timestamp",{ 
         nullable:true,
         default: () => "CURRENT_TIMESTAMP",
         name:"update_time"
         })
     updateTime:Date | null;
         
 }

 

基本的表结构就是这样,然后在 todo.module.ts中导入这个实体

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TodoController } from './todo.controller';
import { TodoService } from './todo.service';
import { t_todo } from './todo.entity'


@Module({
    imports: [TypeOrmModule.forFeature([t_todo])],
    controllers: [TodoController],
    providers: [TodoService],
    exports: [TodoService]
})
export class TodoModule {}

然后 npm run start:dev 来生成表

表

这样表结构就生成了,接着就是逻辑实现了。

数据传输对象

后端写接口,一定要控制好传入params的数据格式,所以要对操作数据库时数据做类型校验,在ts中推荐使用 DTO(数据传输对象)。

新建一个 todo.dto.ts

export class todo {
    summary: string
    details?: string
    is_finished?: number
    is_del?: number
    id?: number
}

路由

接下来可以写请求了,在controller中实现
主要是抛出给前端使用的接口,在这里调用服务的方法。

todo.controller.ts

import { Controller, Get, Post, Put, Body, Delete, Param } from '@nestjs/common';
import { TodoService } from './todo.service';
import { todo } from './todo.dto';

@Controller('todo')

export class TodoController {
    // 初始化服务
    constructor( 
        private readonly todoService: TodoService
    ){ }

    @Get()
    root() {
        return this.todoService.root();
    }

    // 查全部
    @Get()
    getTodo() {
        return this.todoService.getTodo();
    }
    
    // 查一个
    @Get(':id')
    findOne(@Param('id') id: number) {
        return this.todoService.findOne(id)
    }

    // 改
    @Post('update')
    update(@Body() todo:todo) {
        return this.todoService.update(todo)
    }

    // 删
    @Post('delete')
    delete(@Body() id:number) {
        return this.todoService.delete(id)
    }

    // 增
    @Post('create')
    create(@Body() todo: todo): Promise<todo> {
        return this.todoService.create(todo)
    }

    //标记已完成
    @Post('finish')
    finish(@Body() id:number) {
        console.log('aaa');
        return this.todoService.finish(id)
    }
    
}

@nestjs/common中封装了很多装饰器,可以拿来即用。这里只涉及简单的request的使用,了解更多

@Controller('todo') 表示接口输出的路径,在这个下面写的所有接口都是基于 /todo/ 的。

服务

todo.service.ts

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { t_todo as TodoEntity } from './todo.entity';
import { todo } from './todo.dto';
import { Repository } from 'typeorm';

@Injectable()
export class TodoService {
    // 注入相关数据库
    // @InjectRepository(TodoEntity)
    private readonly todoEntity: Repository<TodoEntity>

    root(): string {
        return 'Hello World!';
    }
    // 查全部
    async getTodo(): Promise<todo[]> {
        return await this.todoEntity.find();
    }
    
    // 查一个
    async findOne(id: number): Promise<todo> {
        return await this.todoEntity.findOne({id:id})
    }

    // 增
    async create(todo: todo): Promise<todo> {
        const res = this.todoEntity.create(todo)
        const result = await this.todoEntity.save(res)
        return result;
    }

    //删
    async delete(id:number) {
        return await this.todoEntity.delete(id);
    }

    // 更新
    async update(todo: todo) {
        return await this.todoEntity.update({id: todo.id}, {...todo})
    }

    // 标记为已完成
    async finish(id:number) {
        return await this.todoEntity.update(id, {is_finished:1})
    }
}


Repository 提供了很多可以直接使用的操作数据表的方法。比如 find()findOne()save()update()delete()

基本实现就先这样。

发布了102 篇原创文章 · 获赞 202 · 访问量 40万+

猜你喜欢

转载自blog.csdn.net/zr15829039341/article/details/89511726