🚀 告别重复代码!基于 Axios 的 DSL API 声明库,让接口调用更优雅

还在为每个 API 接口写重复的模板代码而烦恼吗?今天给大家分享一个神器,让你的接口调用代码减少 70%+!

📖 前言

在前端开发中,我们经常需要与后端 API 进行交互。传统的做法是为每个接口写一个函数,比如:

ts 复制代码
// 传统方式 - 每个接口都要写重复的模板代码
export const getUserInfo = (userId: string) =>
  request('/api/users', {
    method: 'GET',
    params: { userId }
  });

export const createUser = (userData: UserData) =>
  request('/api/users', {
    method: 'POST',
    data: userData
  });

export const updateUser = (id: string, userData: UserData) =>
  request(`/api/users/${id}`, {
    method: 'PUT',
    data: userData
  });

这种方式存在以下问题:

  • 代码冗余:每个接口都要写重复的模板代码
  • 维护困难:接口多了之后难以管理
  • 类型安全差:缺乏统一的类型约束
  • 开发效率低:需要为每个接口写大量样板代码

🎯 解决方案:DSL 声明式 API

今天要介绍的是 @siyuan0215/easier-axios-dsl,一个基于 Axios 的 DSL(领域特定语言)API 声明库。

核心特性

  • 🎯 DSL 声明式 API - 使用简洁的字符串声明 API 接口
  • 🔧 类型安全 - 完整的 TypeScript 支持
  • 🚀 零配置 - 开箱即用,无需复杂配置
  • 📦 轻量级 - 基于 Axios,无额外依赖
  • 🌐 跨技术栈 - 支持 Vue、React、Angular 等所有 JS/TS 项目

🚀 快速上手

1. 安装

bash 复制代码
npm install @siyuan0215/easier-axios-dsl

2. 配置请求实例

ts 复制代码
// utils/request.ts
import { init } from '@siyuan0215/easier-axios-dsl';

const { generatorAPIS, requestInstance } = init({
  requestInterceptors: [
    (config) => {
      // 添加认证头
      config.headers.Authorization = `Bearer ${getToken()}`;
      return config;
    },
    (error) => Promise.reject(error)
  ],
  responseInterceptors: [
    (response) => response,
    (error) => {
      // 统一错误处理
      if (error.response?.status === 401) {
        // 处理未授权
      }
      return Promise.reject(error);
    }
  ],
  timeout: 10000,
  baseURL: 'https://api.example.com'
});

export { generatorAPIS, requestInstance };

3. 声明 API 接口

ts 复制代码
// api/index.ts
import { generatorAPIS } from '@/utils/request';

const APIS = {
  // 获取用户信息 - GET 请求,查询参数
  getUserInfo: 'GET /api/users q:userId',
  
  // 创建用户 - POST 请求,请求体数据
  createUser: 'POST /api/users d:name,email,age',
  
  // 更新用户 - PUT 请求,路径参数 + 请求体
  updateUser: 'PUT /api/users/{id} path:id d:name,email',
  
  // 删除用户 - DELETE 请求,路径参数
  deleteUser: 'DELETE /api/users/{id} path:id',
  
  // 文件上传 - POST 请求,FormData
  uploadFile: 'POST /api/upload d.f:file,description',
  
  // 批量操作 - POST 请求,数组数据
  batchUpdate: 'POST /api/users/batch [d] q:dryRun',
  
  // 通配符模式 - 传递所有参数
  wildcardPost: 'POST /api/users d:*'
} as const;

export default generatorAPIS(APIS);

4. 在组件中使用

ts 复制代码
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import APIS from '@/api'

// 响应式数据
const user = ref(null)
const formData = ref({ name: '', email: '', age: 0 })
const uploadProgress = ref(0)

// 获取用户信息
const fetchUserInfo = async () => {
  try {
    const { data } = await APIS.getUserInfo({ userId: '123' })
    user.value = data
  } catch (error) {
    console.error('获取用户信息失败:', error)
  }
}

// 保存用户
const saveUser = async () => {
  try {
    const result = await APIS.createUser({
      name: formData.value.name,
      email: formData.value.email,
      age: formData.value.age
    })
    console.log('用户创建成功:', result)
  } catch (error) {
    console.error('创建用户失败:', error)
  }
}

// 上传文件
const uploadFile = async (file: File) => {
  try {
    const result = await APIS.uploadFile(
      { file, description: '用户头像' },
      undefined, // otherPayload
      {
        onUploadProgress: (progressEvent) => {
          uploadProgress.value = Math.round(
            (progressEvent.loaded * 100) / progressEvent.total
          )
        }
      }
    )
    console.log('文件上传成功:', result)
  } catch (error) {
    console.error('文件上传失败:', error)
  }
}

onMounted(() => {
  fetchUserInfo()
})
</script>

📚 DSL 语法详解

基本格式

ts 复制代码
[HTTP方法] [URL] [参数载体类型]:[参数列表]

参数载体类型

类型 说明 示例 适用场景
q 查询参数 q:page,size GET 请求的 URL 参数
path 路径参数 path:userId 动态路由参数
d 请求体数据 d:name,email POST/PUT 请求的 JSON 数据
d.f FormData d.f:file,description 文件上传
[d] 数组数据 [d] 批量操作
* 通配符 d:* 传递所有参数

完整示例

ts 复制代码
const APIS = {
  // 简单 GET 请求
  getUsers: 'GET /api/users q:page,size,sort',
  
  // 带路径参数的 GET 请求
  getUserById: 'GET /api/users/{id} path:id q:include',
  
  // POST 请求,JSON 数据
  createUser: 'POST /api/users d:name,email,age',
  
  // PUT 请求,路径参数 + 请求体
  updateUser: 'PUT /api/users/{id} path:id d:name,email',
  
  // DELETE 请求,路径参数
  deleteUser: 'DELETE /api/users/{id} path:id',
  
  // 文件上传
  uploadFile: 'POST /api/upload d.f:file,description',
  
  // 批量操作
  batchDelete: 'POST /api/users/batch-delete [d] q:confirm',
  
  // 通配符模式
  flexiblePost: 'POST /api/users d:*'
};

🔧 高级功能

自定义请求配置

ts 复制代码
// 运行时配置
const result = await APIS.downloadFile(
  { id: "123" }, // majorPayload - 主要参数
  undefined, // otherPayload - 额外参数(可选)
  {
    responseType: "blob",
    timeout: 30000,
    headers: {
      "Custom-Header": "value",
    },
    returnResponse: true, // 返回完整的响应对象
  } // RequestConfig - Axios 配置选项
);

参数自动分配

根据 DSL 声明自动将参数分配到不同位置:

ts 复制代码
// DSL: "GET /api/users/{id} path:id q:page,size d:name,email"
const result = await APIS.getUser({
  id: "123",        // → 路径参数: /api/users/123
  page: 1,          // → 查询参数: ?page=1
  size: 10,         // → 查询参数: ?size=10
  name: "John",     // → 请求体: { name: "John" }
  email: "john@example.com" // → 请求体: { email: "john@example.com" }
});

📊 性能对比

传统方式 vs DSL 方式

传统方式(冗余代码):

ts 复制代码
// 需要为每个接口写重复的模板代码
export const getUserInfo = (userId: string) =>
  request("/api/users", {
    method: "GET",
    params: { userId },
  });

export const createUser = (userData: UserData) =>
  request("/api/users", {
    method: "POST",
    data: userData,
  });

export const updateUser = (id: string, userData: UserData) =>
  request(`/api/users/${id}`, {
    method: "PUT",
    data: userData,
  });

DSL 方式(简洁声明):

ts 复制代码
// 一行声明一个接口,自动生成对应函数
const APIS = {
  getUserInfo: "GET /api/users q:userId",
  createUser: "POST /api/users d:*",
  updateUser: "PUT /api/users/{id} path:id d:*",
};

优势:

  • 🎯 代码量减少 70%+ - 大幅减少重复模板代码
  • 🚀 开发效率提升 - 快速声明 API 接口
  • 🔧 维护成本降低 - 统一的接口管理方式
  • 🎨 类型安全 - 完整的 TypeScript 支持

🌐 跨技术栈支持

这个库不仅支持 Vue,还支持所有主流技术栈:

React (Hooks)

tsx 复制代码
import { useState, useEffect } from 'react'
import APIS from '@/api'

const UserProfile = () => {
  const [user, setUser] = useState(null)
  
  const fetchUserInfo = async () => {
    const { data } = await APIS.getUserInfo({ userId: '123' })
    setUser(data)
  }
  
  useEffect(() => {
    fetchUserInfo()
  }, [])
  
  return <div>{/* 组件模板 */}</div>
}

Angular (Service)

ts 复制代码
@Injectable({
  providedIn: 'root'
})
export class UserService {
  async getUserInfo(userId: string) {
    const { data } = await APIS.getUserInfo({ userId })
    return data
  }
}

🧪 测试保障

项目包含完整的单元测试套件,测试覆盖率达到 88.76%:

bash 复制代码
# 运行测试
npm test

# 运行测试并生成覆盖率报告
npm run coverage

测试覆盖范围包括:

  • ✅ 核心功能测试
  • ✅ DSL 解析测试
  • ✅ 参数处理测试
  • ✅ 拦截器测试
  • ✅ FormData 处理测试
  • ✅ 错误处理测试
  • ✅ 边界情况测试

🎯 适用场景

这个库特别适合以下场景:

  1. 大型项目 - 接口数量多,需要统一管理
  2. 团队协作 - 统一的接口调用规范
  3. 快速开发 - 减少重复代码,提高开发效率
  4. 类型安全 - 需要完整的 TypeScript 支持
  5. 跨技术栈 - 需要在不同框架间复用接口逻辑

📦 安装使用

bash 复制代码
# 安装
npm install @siyuan0215/easier-axios-dsl

# 或者使用 yarn
yarn add @siyuan0215/easier-axios-dsl

# 或者使用 pnpm
pnpm add @siyuan0215/easier-axios-dsl

🔗 相关链接

💡 总结

@siyuan0215/easier-axios-dsl 通过 DSL 声明式的方式,让我们可以用一行字符串声明一个 API 接口,自动生成对应的函数。这种方式不仅减少了大量重复代码,还提供了更好的类型安全和开发体验。

如果你正在为 API 接口的重复代码而烦恼,或者想要一个统一的接口管理方案,不妨试试这个库。相信它会为你的开发带来全新的体验!


如果这篇文章对你有帮助,欢迎点赞、收藏、分享! 🚀

有任何问题或建议,欢迎在评论区讨论! 💬

相关推荐
用户6698206112982几秒前
js今日理解 blob和arrayBuffer 二进制数据
前端·javascript
想想肿子会怎么做3 分钟前
Flutter 环境安装
前端·flutter
断竿散人4 分钟前
Node 版本管理工具全指南
前端·node.js
转转技术团队5 分钟前
「快递包裹」视角详解OSI七层模型
前端·面试
1024小神10 分钟前
Ant Design这个日期选择组件最大值最小值的坑
前端·javascript
卸任11 分钟前
Electron自制翻译工具:自动更新
前端·react.js·electron
安禅不必须山水12 分钟前
Express+Vercel+Github部署自己的Mock服务
前端
哈撒Ki15 分钟前
快速入门zod4
前端·node.js
用户游民44 分钟前
Flutter 项目热更新方案对比与实现指南
前端
泉城老铁1 小时前
前端实现人体动作识别
前端·vue.js