还在为每个 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 处理测试
- ✅ 错误处理测试
- ✅ 边界情况测试
🎯 适用场景
这个库特别适合以下场景:
- 大型项目 - 接口数量多,需要统一管理
- 团队协作 - 统一的接口调用规范
- 快速开发 - 减少重复代码,提高开发效率
- 类型安全 - 需要完整的 TypeScript 支持
- 跨技术栈 - 需要在不同框架间复用接口逻辑
📦 安装使用
bash
# 安装
npm install @siyuan0215/easier-axios-dsl
# 或者使用 yarn
yarn add @siyuan0215/easier-axios-dsl
# 或者使用 pnpm
pnpm add @siyuan0215/easier-axios-dsl
🔗 相关链接
- 📦 NPM 包 : @siyuan0215/easier-axios-dsl
- 📖 GitHub : 项目地址
- 📚 文档 : 详细文档
💡 总结
@siyuan0215/easier-axios-dsl
通过 DSL 声明式的方式,让我们可以用一行字符串声明一个 API 接口,自动生成对应的函数。这种方式不仅减少了大量重复代码,还提供了更好的类型安全和开发体验。
如果你正在为 API 接口的重复代码而烦恼,或者想要一个统一的接口管理方案,不妨试试这个库。相信它会为你的开发带来全新的体验!
如果这篇文章对你有帮助,欢迎点赞、收藏、分享! 🚀
有任何问题或建议,欢迎在评论区讨论! 💬