前端转后端?用 Vue 的思维学 NestJS,真香!

引言

作为一名前端开发者,你是否想过扩展自己的技术栈,尝试后端开发?

其实 NestJS 的学习曲线比你想象的平缓得多------因为它的设计思想和 Vue 有很多相似之处!

本文将用前端熟悉的概念,带你快速上手 NestJS。


一、NestJS 是什么?

NestJS 是一个用于构建高效、可扩展的 Node.js 服务端应用程序框架。它使用 TypeScript 构建,结合了 OOP、FP 和 FRP 的元素。

简单来说:

如果说 Vue 是前端界的"组件化框架" ,那么 NestJS 就是后端界的"模块化框架"


二、Vue vs NestJS:概念对照表

Vue 概念 NestJS 对应概念 说明
组件 (Component) 控制器 (Controller) 处理用户交互/请求
组合式函数 (Composables) 服务 (Service) 封装可复用的业务逻辑
Props DTO 定义数据结构和类型
Pinia/Vuex Store Module 状态/功能模块化组织
Vue Router 路由装饰器 (@Get/@Post) 定义访问路径
provide/inject 依赖注入 (DI) 跨组件/模块共享实例
生命周期钩子 生命周期钩子 应用启动、请求处理等阶段

三、从 Vue 组件到 NestJS 控制器

Vue 组件写法

vue 复制代码
<script setup>
import { ref } from 'vue'
import { useUserStore } from '@/stores/user'

const props = defineProps({
  userId: String
})

const userStore = useUserStore()

const fetchUser = () => {
  return userStore.getUser(props.userId)
}
</script>

NestJS 控制器写法

typescript 复制代码
import { Controller, Get, Param } from '@nestjs/common'
import { PersonService } from './person.service'

@Controller('api/person')
export class PersonController {
  constructor(private readonly personService: PersonService) {}

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.personService.findOne(+id)
  }
}

类比理解

  • @Controller('api/person') ≈ 组件的 name + 基础路由路径
  • @Get(':id') ≈ Vue Router 的 path: '/person/:id'
  • @Param('id')useRoute().params.id
  • constructor 注入const store = useStore()

四、DTO:相当于 Vue 的 Props 类型定义

Vue 的 Props 类型定义

typescript 复制代码
interface UserProps {
  name: string
  age: number
}

NestJS 的 DTO

typescript 复制代码
// dto/create-person.dto.ts
export class CreatePersonDto {
  name: string
  age: number
}

实际使用

typescript 复制代码
@Post()
create(@Body() createPersonDto: CreatePersonDto) {
  return this.personService.create(createPersonDto)
}

类比理解

  • DTO ≈ Props 类型定义 + 表单校验规则
  • @Body() ≈ 获取 POST 请求的 body,类似 v-model 绑定的数据

五、Service:相当于 Composables

Vue 的 Composables

typescript 复制代码
// composables/useUser.ts
export function useUser() {
  const fetchUser = async (id: string) => {
    // 请求逻辑
  }
  return { fetchUser }
}

NestJS 的 Service

typescript 复制代码
import { Injectable } from '@nestjs/common'

@Injectable()
export class PersonService {
  create(createPersonDto: CreatePersonDto) {
    return 'This action adds a new person'
  }

  findOne(id: number) {
    return `This action returns a #${id} person`
  }

  update(id: number, updatePersonDto: UpdatePersonDto) {
    return `This action updates a #${id} person`
  }

  remove(id: number) {
    return `This action removes a #${id} person`
  }
}

类比理解

  • @Injectable()export function useXXX(),表示这是一个可复用的服务
  • Service 中封装业务逻辑,Controller 只负责接收请求和返回响应

六、Module:相当于 Pinia 的 Store 模块

Vue 的 Pinia Store

typescript 复制代码
// stores/user.ts
export const useUserStore = defineStore('user', {
  state: () => ({ ... }),
  actions: { ... }
})

NestJS 的 Module

typescript 复制代码
import { Module } from '@nestjs/common'
import { PersonController } from './person.controller'
import { PersonService } from './person.service'

@Module({
  imports: [],
  controllers: [PersonController],
  providers: [PersonService],
  exports: [PersonService]
})
export class PersonModule {}

根模块

typescript 复制代码
@Module({
  imports: [PersonModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

类比理解

  • Module ≈ Pinia Store 模块,用于组织和隔离功能
  • imports ≈ 引入其他 store 模块
  • providers ≈ 模块内部的状态和方法
  • exports ≈ 暴露给其他模块使用的 API

七、依赖注入:比 provide/inject 更强大

Vue 的依赖注入

vue 复制代码
<!-- 祖先组件 -->
<script setup>
import { provide } from 'vue'
provide('userService', new UserService())
</script>

<!-- 后代组件 -->
<script setup>
import { inject } from 'vue'
const userService = inject('userService')
</script>

NestJS 的依赖注入

typescript 复制代码
@Controller('api/person')
export class PersonController {
  constructor(private readonly personService: PersonService) {}
}

优势

  1. 自动单例管理:类似 Vue 的 provide 默认只创建一次实例
  2. 自动解析依赖:不需要手动 inject,按类型自动匹配
  3. 便于测试:可以轻松 Mock 服务进行单元测试

八、装饰器语法:类似 Vue 的宏函数

Vue 3 的宏函数

vue 复制代码
<script setup>
defineProps({ ... })
defineEmits(['click'])
defineExpose({ ... })
</script>

NestJS 的装饰器

typescript 复制代码
@Controller('api/person')
@Get(':id')
@Post()
@Body()
@Param('id')
@Query('name')
@Injectable()
@Module({ ... })

类比理解

装饰器 ≈ Vue 的宏函数 + 指令,提供声明式的元数据标记


九、5 种常见请求方式对照示例

根据实际项目中的接口设计,以下是前端 5 种请求方式与后端处理的完整对照:

1. URL 参数(@Param)

前端:

javascript 复制代码
const res = await axios.get('/api/person/1')

后端:

typescript 复制代码
@Get(':id')
findOne(@Param('id') id: string) {
  return `This is a person with id: ${id}`
}

2. Query 参数(@Query)

前端:

javascript 复制代码
const res = await axios.get('/api/person/find', {
  params: { name: '张三', age: 20 }
})

后端:

typescript 复制代码
@Get('find')
query(@Query('name') name: string, @Query('age') age: number) {
  return `name: ${name}, age: ${age}`
}

3. JSON 请求体(@Body)

前端:

javascript 复制代码
const res = await axios.post('/api/person', {
  name: '张三',
  age: 20
})

后端:

typescript 复制代码
@Post()
body(@Body() createPersonDto: CreatePersonDto) {
  return `name: ${createPersonDto.name}, age: ${createPersonDto.age}`
}

4. Form URL Encoded(@Body)

前端:

javascript 复制代码
const res = await axios.post('/api/person', Qs.stringify({
  name: '张三',
  age: 20
}), {
  headers: { 'content-type': 'application/x-www-form-urlencoded' }
})

后端:

typescript 复制代码
@Post()
body(@Body() createPersonDto: CreatePersonDto) {
  return `name: ${createPersonDto.name}, age: ${createPersonDto.age}`
}

5. FormData 文件上传(@UploadedFiles)

前端:

javascript 复制代码
const data = new FormData()
data.set('name', '张三')
data.set('age', 20)
data.set('file1', fileInput.files[0])
data.set('file2', fileInput.files[1])

const res = await axios.post('/api/person/file', data, {
  headers: { 'content-type': 'multipart/form-data' }
})

后端:

typescript 复制代码
@Post('file')
@UseInterceptors(AnyFilesInterceptor({ dest: 'uploads' }))
body2(
  @Body() createPersonDto: CreatePersonDto,
  @UploadedFiles() files: Array<Express.Multer.File>
) {
  return `name: ${createPersonDto.name}, age: ${createPersonDto.age}`
}

完整控制器代码

typescript 复制代码
// person.controller.ts
import { Controller, Get, Post, Body, Query, Param, UseInterceptors, UploadedFiles } from '@nestjs/common'
import { AnyFilesInterceptor } from '@nestjs/platform-express'

@Controller('api/person')
export class PersonController {
  // 1. URL 参数
  @Get(':id')
  findOne(@Param('id') id: string) {
    return `This is a person with id: ${id}`
  }

  // 2. Query 参数
  @Get('find')
  query(@Query('name') name: string, @Query('age') age: number) {
    return `name: ${name}, age: ${age}`
  }

  // 3 & 4. JSON / Form URL Encoded
  @Post()
  body(@Body() createPersonDto: CreatePersonDto) {
    return `name: ${createPersonDto.name}, age: ${createPersonDto.age}`
  }

  // 5. FormData 文件上传
  @Post('file')
  @UseInterceptors(AnyFilesInterceptor({ dest: 'uploads' }))
  uploadFile(
    @Body() createPersonDto: CreatePersonDto,
    @UploadedFiles() files: Array<Express.Multer.File>
  ) {
    return { message: '上传成功', name: createPersonDto.name, files }
  }
}

十、前端开发者学 NestJS 的优势

优势 说明
TypeScript 无缝衔接 和 Vue 3 + TS 的开发体验一致
装饰器语法熟悉 类似 Vue 的宏函数,降低学习成本
模块化思维 Vue 的组件化思维直接迁移到后端模块
依赖注入理解 Vue 的 provide/inject 让你更容易理解 DI
响应式编程 RxJS 和 Vue 的响应式系统有异曲同工之妙

总结

NestJS 的设计哲学和 Vue 有很多相通之处:

前端思维 后端实现
组件化开发 控制器 + 服务分离
Props 类型校验 DTO 数据验证
Pinia 状态管理 Module 模块组织
Composables 复用 Service 服务封装
provide/inject 依赖注入系统

如果你已经熟悉 Vue,那么学习 NestJS 只需要转换视角------从"操作 DOM 和状态"转变为"处理请求和数据"。

相信凭借前端的基础,你能很快上手 NestJS,成为真正的全栈开发者!


推荐学习路径

  1. 先理解 Controller、Service、Module 三大核心概念
  2. 学习装饰器的使用(@Get、@Post、@Body 等)
  3. 掌握 DTO 和管道验证(类似表单校验)
  4. 了解 Guards、Interceptors、Middleware(类似路由守卫、请求拦截)
  5. 实践一个完整的 CRUD 项目

希望这篇文章能帮助你顺利踏上后端开发之旅!

相关推荐
当时只道寻常8 小时前
NestJS Redis 原子限流守卫 防刷防攻击
后端·nestjs
踩着两条虫9 小时前
VTJ.PRO 在线应用开发平台的Open API 与外部集成
低代码·ai编程·nestjs
www_stdio1 天前
🚀 从 Event Loop 到 AI Agent:我的 Node.js 全栈进阶之路
前端·node.js·nestjs
Bigger1 天前
🚀 开源发布!从 0 到 1,使用 Next.js + Nest.js 构建全栈自动化数据分析 AI Agent
agent·nestjs·next.js
踩着两条虫3 天前
VTJ.PRO 在线应用开发平台的数据库与基础设施
数据库·架构·nestjs
踩着两条虫4 天前
VTJ.PRO 在线应用开发平台的后端模块系统
后端·架构·nestjs
踩着两条虫4 天前
VTJ.PRO 在线应用开发平台的业务模块(应用、DSL、模板、订单、智能体、技能)
后端·agent·nestjs
踩着两条虫4 天前
VTJ.PRO 在线应用开发平台的核心模块(用户、认证、RBAC、缓存、设置)
后端·低代码·nestjs
AAA阿giao7 天前
从零到精通 NestJS:深度剖析待办事项(Todos)项目,全面解析 Nest 架构、模块与数据流
架构·typescript·node.js·nestjs·全栈开发·后端框架