都2023了,不会有人手撸API函数吧

简介: 都2023了,不会有人手撸API函数吧如果你正在开发一个前端程序,后端有指定规范的 API, 那你该看看这篇文章啦~

都2023了,不会有人手撸API函数吧

如果你正在开发一个前端程序,后端有指定规范的 API, 那你该看看这篇文章啦~

本文章示例用到了TypeScript,如果觉得不适,看一下核心代码即可。

业务场景举例

API 通常是提供在不同实体上执行增删改查(CRUD)造作的一组接口。我们通常在我们的前端项目中为这些每一个接口提供一个函数,这些函数的功能非常的相似,只是为了服务于不用的实体。举个例子,假设我们有这些函数。

// api/user.ts

import http from '@/utils/http';

// 登录参数
export interface LoginData {
   
  /** 登陆编码 */
  loginCode: string;
  password: string;
}

/** 用户信息 */
export interface UserInfo {
   
  /** 状态 */
  status: string;
  /** 创建人 */
  createBy: string;
  /** 创建时间 */
  createDate: string;
  /** 更新人 */
  updateBy: string;
  /** 更新时间 */
  updateDate: string;
  remarks: string | null;
  /** 用户编码 */
  userCode: string;
  /** 登陆编码 */
  loginCode: string;
  /** 用户名 */
  userName: string;
  /** 密码 */
  password: string;
  /** 邮件 */
  email: string;
  /** 手机 */
  mobile: string | null;
  /** 电话 */
  phone: string | null;
  /** 性别 */
  sex: string;
  /** 头像 */
  avatar: string | null;
  /** 个性签名 */
  sign: string | null;
  /** 微信开发id */
  wxOpenId: string | null;
  /** 手机imei */
  mobileImei: string | null;
  /** 用户类型 */
  userType: string;
  /** 用户类型引用编号 */
  refCode: string | null;
  /** 用户类型引用名称 */
  refName: string | null;
  /** 管理员类型 */
  mgrType: string;
  /** 密码强度等级 */
  pwdSecurityLevel: string | null;
  /** 用户权重 */
  userWeight: number;
}

/** 登录信息 */
export interface LoginInfo {
   
  tokenName: string;
  tokenValue: string;
  isLogin: boolean;
  loginId: string;
  loginType: string;
  tokenTimeout: number;
  sessionTimeout: number;
  tokenSessionTimeout: number;
  tokenActivityTimeout: number;
  loginDevice: string;
  tag: string;
}

export interface LoginRes {
   
  loginInfo: LoginInfo;
  userInfo: UserInfo;
}
/** 登录接口 */
export function login(data: LoginData) {
   
  return http.post<LoginRes>({
    url: '/login', data });
}

/** 登出接口 */
export function logout() {
   
  return http.post<null>({
    url: '/logout' });
}
/** 获取当前登录的用户信息 */
export function getLoginUserInfo() {
   
  return http.get<UserInfo>({
    url: '/loginUserInfo' });
}
/** 获取当前登录信息 */
export function getTokenInfo() {
   
  return http.get<LoginInfo>({
    url: '/tokenInfo' });
}

类似的功能可能存在于其他实体,例如:角色、权限、用户...但是我们可以用一个简单的函数调用来代替这些函数:

// api/system-privilege/users.ts

import {
    ServiceProxy } from '@/shared';
import {
    UserInfo } from '@/api/user';
import {
    ListDataRes } from '@/api/common';

// 参数接口
export interface ListDataParams {
   
  userName?: string;
}
export interface SaveParams {
   
  userCode?: string;
  loginCode: string;
  userName?: string;
  mobile?: string;
  email?: string;
  sex?: string;
  sign?: string;
  userType: string;
  userWeight: number;
  mgrType: string;
}

// 核心
const service = new ServiceProxy('/api/sys/user');

/**
 * 获取用户列表
 * @param {object} params ListDataParams
 * @param {string} params.userName
 * @returns
 */
export function getPaged(
  params: ListDataParams
): Promise<ListDataRes<UserInfo>> {
   
  return service.getPaged(params);
}

/**
 * 修改或新增用户
 * @param {object} params 用户保存实体
 * @param {string} params.userCode 用户编码,用户id,为空则新增,不为空则修改
 * @param {string} params.loginCode 登陆编码,用户登陆的账号
 * @param {string} params.userName 用户名
 * @param {string} params.mobile 手机
 * @param {string} params.email 邮件
 * @param {string} params.sex 性别
 * @param {string} params.sign 个性签名
 * @param {string} params.userType 用户类型
 * @param {number} params.userWeight 用户权重
 * @param {string} params.mgrType 管理员类型
 * @returns
 */
export function createOrUpdate(params: SaveParams): Promise<null> {
   
  return service.createOrUpdate(params);
}

/**
 * 获取用户信息
 * @param {string} params.id 类型主键
 * @returns
 */
export function getById(params: {
    id: string }): Promise<null> {
   
  return service.getById(params);
}
/**
 * 获取用户信息
 * @param {string} params.id 类型主键
 * @returns
 */
export function del(params: {
    id: string }): Promise<null> {
   
  return service.delete(params);
}

然后像这样去使用:

import {
    getPaged, createOrUpdate, getById } from '@/api/system-privilege/users';

// 一下返回的是Promise

getPaged({
    ...params.res, pageNum: params.pageNum, pageSize: params.pageSzie });
createOrUpdate(state.data);
getById({
    id: props.id })

你可能会问为什么?有一些很好的理由:

  • 减少了代码行数:你编写的代码,和当你离开公司时其他人维护的代码
  • 强制执行 API 函数的命名约定,这可以增加代码的可读性和可维护性
  • 同时 ServiceProxy 的实现使用的 class,当API不符合要求时,可以通过继承等方式进行扩展(业务场景:对接第三方接口)。

此处ServiceProxy就类似于一个高级可扩展的 CRUD 构造器。

高级构造器 ServiceProxy 的实现

以下便是ServiceProxy基础实现,如果觉得简单,是可以进行增强和扩展的哟。

import http from '@/utils/http';
import VAxios from '@/utils/http/Axios';

export default class ServiceProxies {
   
  private instance: VAxios;

  private baseUrl: string;

  private url: string;

  constructor(url?: string, baseUrl?: string, instance?: VAxios) {
   
    this.instance = instance || http;

    this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : '';

    this.url = url !== undefined && url !== null ? url : '';
  }

  /**
   * 获取列表数据
   * @returns
   */
  getPaged<T>(params: T) {
   
    return this.instance.post({
    url: this.url, data: {
    ...params } });
  }

  /**
   * 通过ID获取详细信息
   * @returns
   */
  getById<T>(params: T) {
   
    return this.instance.get({
    url: this.url, params: {
    ...params } });
  }

  /**
   * 通过拼接构造器与传入的api进行Get请求,类似扩展构造器的url
   * @param api 扩展api
   * @param params 参数值
   */
  getApi(api: string, params: any) {
   
    return this.instance.get({
   
      url: `${this.url}${api}`,
      params: {
    ...params },
    });
  }

  /**
   * 通过拼接构造器与传入的api进行Post请求,类似扩展构造器的url
   * @param api 扩展api
   * @param params 参数值
   */
  postApi(api: string, params: any) {
   
    return this.instance.post({
   
      url: `${this.url}${api}`,
      data: {
    ...params },
    });
  }

  /**
   * 通过拼接构造器与传入的api进行Put请求,类似扩展构造器的url
   * @param api 扩展api
   * @param params 参数值
   */
  putApi(api: string, params: any) {
   
    return this.instance.put({
   
      url: `${this.url}${api}`,
      data: {
    ...params },
    });
  }

  /**
   * 通过拼接构造器与传入的api进行Delete请求,类似扩展构造器的url
   * @param api 扩展api
   * @param params 参数值
   */
  deleteApi(api: string, params: any) {
   
    return this.instance.delete({
   
      url: `${this.url}${api}`,
      params: {
    ...params },
    });
  }

  /**
   * 新增或者编辑
   * @returns
   */
  createOrUpdate<T>(params: T) {
   
    return this.instance.put({
    url: this.url, params: {
    ...params } });
  }
}

用法:

import {
    ServiceProxy } from '@/shared';

const service = new ServiceProxy('/api/sys/user');
const service = new ServiceProxy('/api/sys/role');
const service = new ServiceProxy('/api/sys/menu');

// 然后再去编写业务逻辑代码
// 相关示例可以观看上述的用户示例

结尾

看到这里小伙伴们是不是有一种发现新大陆的感觉。

快动动你们的小手指敲起来吧~

当然,如果觉得有什么不合理的地方,可以指出来哦。

目录
相关文章
|
2月前
|
存储 JavaScript API
活用 Composition API 核心函数,打造卓越应用(上)
活用 Composition API 核心函数,打造卓越应用(上)
|
2月前
|
缓存 JavaScript 算法
活用 Composition API 核心函数,打造卓越应用(下)
活用 Composition API 核心函数,打造卓越应用(下)
|
2月前
|
人工智能 关系型数据库 Serverless
Serverless 应用引擎常见问题之API生成的函数镜像改为自定义的镜像如何解决
Serverless 应用引擎(Serverless Application Engine, SAE)是一种完全托管的应用平台,它允许开发者无需管理服务器即可构建和部署应用。以下是Serverless 应用引擎使用过程中的一些常见问题及其答案的汇总:
Qt 窗口常用位置API函数 & 绘图原理 & 双缓冲机制 总结
Qt 窗口常用位置API函数 & 绘图原理 & 双缓冲机制 总结
|
2月前
|
Java 数据库连接 API
Java 学习路线:基础知识、数据类型、条件语句、函数、循环、异常处理、数据结构、面向对象编程、包、文件和 API
Java 是一种广泛使用的、面向对象的编程语言,始于1995年,以其跨平台性、安全性和可靠性著称,应用于从移动设备到数据中心的各种场景。基础概念包括变量(如局部、实例和静态变量)、数据类型(原始和非原始)、条件语句(if、else、switch等)、函数、循环、异常处理、数据结构(如数组、链表)和面向对象编程(类、接口、继承等)。深入学习还包括包、内存管理、集合框架、序列化、网络套接字、泛型、流、JVM、垃圾回收和线程。构建工具如Gradle、Maven和Ant简化了开发流程,Web框架如Spring和Spring Boot支持Web应用开发。ORM工具如JPA、Hibernate处理对象与数
118 3
|
2月前
|
JavaScript API
Vue3 API函数及功能
Vue3 API函数及功能
13 0
|
2月前
|
存储 安全 Linux
【Linux 创建临时文件 API】编程中的瞬息之光:临时文件的艺术与智慧 tmpnam,tmpfile,mkstemp,mkdtemp等函数解析...
【Linux 创建临时文件 API】编程中的瞬息之光:临时文件的艺术与智慧 tmpnam,tmpfile,mkstemp,mkdtemp等函数解析...
39 0
|
2月前
|
数据库连接 API 数据库
SQLite3 数据库 C语言API 打开函数sqlite3_open 详解
SQLite3 数据库 C语言API 打开函数sqlite3_open 详解
96 0
|
2月前
|
编译器 API C++
【C++ 动态库设计】动态库中的模板函数:解决如果将模板函数封装成API库
【C++ 动态库设计】动态库中的模板函数:解决如果将模板函数封装成API库
109 0
|
2月前
|
存储 API 数据安全/隐私保护
FreeRTOS入门教程(信号量的概念及API函数使用)
FreeRTOS入门教程(信号量的概念及API函数使用)
189 0