javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > TypeScript封装RESTful BaseAPI

TypeScript封装通用RESTful BaseAPI的实现示例

作者:VOLUN

本文主要介绍了TypeScript封装通用RESTful BaseAPI的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

本文适用场景:Vue3+TS+Axios 中后台管理系统、遵循RESTful接口规范项目、大量同质化增删改查业务

阅读收益:一套可直接落地的通用CRUD封装、区分简易/复杂分页查询最佳实践、对接自定义表格Hook完整用法、RPC旧式接口迁移方案

前置依赖:项目已封装全局axios请求实例 @/utils/http

一、项目痛点

开发中后台系统,绝大多数业务模块(用户、角色、菜单、商品、部门)接口高度同质化:分页列表、详情、新增、编辑、单删、批量删除。

传统写法存在大量问题:

基于以上问题,本文封装一套符合企业级RESTful规范的通用 createBaseAPI,一行代码生成全套CRUD接口,开箱即用。

二、统一RESTful接口约定

适配说明:本文约定为适配中后台最优方案,可根据后端接口规范,自行修改请求路径、请求方式、批量删除入参格式

以资源 users 为例,基础路径 baseUrl: /api/users,全套接口规范如下:

请求方法接口路径业务说明适用场景
GET/api/users简易分页列表筛选条件少、无数组/日期范围,参数拼URL
POST/api/users/search复杂分页查询多选、日期区间、多表单筛选,参数放Body,规避URL超长
GET/api/users/:id获取单条详情表单回显、弹窗详情
POST/api/users新增资源新增业务数据
PUT/api/users/:id全量编辑资源覆盖式修改数据
DELETE/api/users/:id单条删除单行删除操作
DELETE/api/users批量删除入参 {ids: string[]},表格多选删除

核心选型技巧

1. 简单筛选:优先GET list,写法简洁、缓存友好

2. 复杂筛选:必用POST search,避免浏览器URL长度限制、特殊参数转义问题

3. 后端批量路径自定义:可手动扩展方法适配 /batch-delete 这类非标接口

三、核心工具类 createBaseAPI 源码

新建文件 @/utils/createBaseAPI.ts,完整类型封装,支持泛型约束,完美适配TS类型提示

import { http } from '@/utils/http'

/** 后端统一分页返回结构体 */
export interface PageResult<T> {
  list: T[]
  total: number
}

/** 通用分页入参 */
export interface PageParams {
  page: number
  size: number
}

/** 业务自定义参数映射:列表筛选/新增/编辑类型约束 */
interface QueryMap {
  /** 列表查询筛选参数 */
  list?: Record<string, any>
  /** 新增请求体 */
  create?: Record<string, any>
  /** 更新请求体 */
  update?: Record<string, any>
}

/**
 * 生成RESTful通用CRUD API
 * @param baseUrl 资源基础接口地址
 * @returns 内置全套增删改查方法
 */
export function createBaseAPI<T, Q extends QueryMap = QueryMap>(params: { baseUrl: string }) {
  const { baseUrl } = params

  return {
    /** GET /resource/:id 获取详情 */
    getById(id: string) {
      return http.get<T>(`${baseUrl}/${id}`)
    },

    /** GET /resource 简易分页列表 */
    list(params: PageParams & Q['list']) {
      return http.get<PageResult<T>>(baseUrl, params)
    },

    /** POST /resource/search 复杂分页筛选 */
    search(params: PageParams & Q['list']) {
      return http.post<PageResult<T>>(`${baseUrl}/search`, params)
    },

    /** POST /resource 新增资源 */
    create(data: Q['create']) {
      return http.post<T>(baseUrl, data)
    },

    /** PUT /resource/:id 全量更新资源 */
    update(id: string, data: Q['update']) {
      return http.put<T>(`${baseUrl}/${id}`, data)
    },

    /** DELETE /resource/:id 单条删除 */
    remove(id: string) {
      return http.delete<void>(`${baseUrl}/${id}`)
    },

    /** DELETE /resource 批量删除 */
    removeBatch(ids: string[]) {
      return http.delete<void>(baseUrl, { data: { ids } })
    }
  }
}

四、业务模块快速定义API

以用户模块为例,新建 @/apis/user.ts,仅需定义实体类型+自定义筛选类型,一行生成全部CRUD,非标接口单独拓展即可。

import { createBaseAPI } from '@/utils/createBaseAPI'
import type { PageResult } from '@/utils/createBaseAPI'

/** 用户实体类型 */
export interface UserItem {
  id: string
  name: string
  age: number
  phone: string
  address: string
  status: number
}

/** 用户角色附属类型(拓展非标接口) */
export interface UserRoleItem {
  id: string
  roleName: string
}

/** 自定义用户模块:列表筛选、新增、编辑入参类型 */
interface UserQuery {
  list?: {
    name?: string
    status?: number
    // 多选状态筛选
    statusList?: number[]
    // 日期区间筛选
    dateRange?: string[]
  }
  // 新增字段约束
  create?: Partial<UserItem>
  // 编辑字段约束
  update?: Partial<UserItem>
}

/** 自动生成用户全套CRUD接口 */
export const userAPI = createBaseAPI<UserItem, UserQuery>({ baseUrl: '/api/users' })

/** ========== 非标REST接口单独拓展 ========== */
/** 获取用户绑定角色 */
export function getUserRoleList(id: string) {
  return http.get<UserRoleItem[]>(`/api/users/${id}/roles`)
}

五、页面直接调用使用

组合式API页面直接调用,TS自动推导入参出参,自带代码提示,无需重复写url和method

import { userAPI } from '@/apis/user'

// 1. 获取详情
const detail = await userAPI.getById('1')

// 2. 简易分页查询(少量筛选条件)
const pageData = await userAPI.list({ page: 1, size: 10, name: '', status: 1 })

// 3. 复杂条件查询(多选、日期范围)
const searchData = await userAPI.search({
  page: 1,
  size: 10,
  name: '',
  statusList: [1, 2],
  dateRange: ['2024-01-01', '2024-12-31']
})

// 4. 新增用户
await userAPI.create({ name: '张三', age: 18, status: 1 })

// 5. 编辑用户
await userAPI.update('1', { name: '李四' })

// 6. 单条删除
await userAPI.remove('1')

// 7. 批量删除
await userAPI.removeBatch(['1', '2', '3'])

六、适配项目通用表格Hook useTable

中后台必备表格Hook联动,自动判断筛选条件,动态切换 GET/list / POST/search,优化请求体验,适配Element Plus/Ant Design Vue表格。

import { userAPI } from '@/apis/user'
import { useTable } from '@/hooks/useTable'
import { computed, reactive } from 'vue'

// 表格筛选条件
const queryParams = reactive({
  name: '',
  status: undefined as number | undefined,
  statusList: [] as number[],
  dateRange: [] as string[]
})

// 判定:存在数组/日期条件,自动走POST复杂查询
const useSearchAPI = computed(() =>
  queryParams.statusList.length > 0 || queryParams.dateRange.length > 0
)

// 表格全局状态、请求、分页封装
const { tableData, pagination, search, loading } = useTable({
  listAPI: (pageInfo) => useSearchAPI.value
    ? userAPI.search({ ...pageInfo, ...queryParams })
    : userAPI.list({ ...pageInfo, ...queryParams }),
  rowKey: 'id',
  deleteAPI: (ids) => userAPI.removeBatch(ids)
})

七、旧式RPC接口 vs RESTful新规范对照

适配老旧项目迁移改造,快速对齐新旧接口语义,方便统一项目接口风格

旧式RPC风格接口标准化RESTful接口
GET /api/user/queryById?id=1GET /api/users/1
GET /api/user/pageQueryListGET /api/users / POST /api/users/search
POST /api/user/saveInsertPOST /api/users
POST /api/user/saveUpdatePUT /api/users/:id
POST /api/user/deleteDELETE /api/users/:id
POST /api/user/batchDeleteDELETE /api/users

补充适配方案

后端提供「新增表单默认值」接口 GET /api/users/new,不属于基础CRUD,直接在业务API手动拓展即可,不改动基础封装代码。

八、项目自定义改造指南

1. 适配PATCH局部更新

后端使用PATCH做部分字段更新,在createBaseAPI内新增方法即可:

/** PATCH 局部更新 */
patch(id: string, data: Q['update']) {
  return http.patch<T>(`${baseUrl}/${id}`, data)
}

2. 适配非标批量删除路径

后端批量删除为 POST /api/users/batch-del,业务层直接拓展方法:

// userAPI拓展自定义批量删除
userAPI.batchDel = (ids: string[]) => http.post('/api/users/batch-del', { ids })

3. 修改分页字段

后端分页参数不为page/size,直接修改PageParams全局类型即可全局生效。

九、总结

后续新增任意业务模块(角色、菜单、字典),仅需3行代码即可生成全套CRUD接口,开发效率直接翻倍✨

到此这篇关于TypeScript封装通用RESTful BaseAPI的实现示例的文章就介绍到这了,更多相关TypeScript封装RESTful BaseAPI内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文