Appearance
前端 API 层 Mock 开关设计方案 - 方法总结
一、背景与目标
问题场景
- 前端页面开发时,后端接口尚未开发完成
- 需要使用 Mock 数据进行前端开发和测试
- 后期接口开发完成后,需要最小化改动切换到真实 API
核心目标
- 前端先行:不依赖后端接口,可独立开发
- 平滑切换:Mock → 真实 API 切换只需修改一个开关
- 最小改动:切换时前端页面代码无需修改
- 数据适配:通过 Transform 层适配后端数据格式差异
二、架构设计
目录结构
src/api/
├── config.ts # 全局 Mock 开关配置
└── strategy-workbench/ # 业务模块 API
├── index.ts # API 统一入口(包含 Mock 开关 +Mock 数据+ Transform)三层架构
┌─────────────────────────────────────────────────────────────┐
│ 页面层 (Vue Components) │
│ import { getStrategyList } from '#/api/xxx/index' │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ API 层 (index.ts) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Mock 开关 │ │ Transform │ │ API 方法封装 │ │
│ │ IS_USE_MOCK │ │ 数据转换 │ │ getStrategyList() │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
┌───────────────┴───────────────┐
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────────┐
│ Mock 数据层 (mock.ts) │ │ 真实 API (requestClient) │
│ generateMockData() │ │ GET /strategy/list │
└─────────────────────────┘ └─────────────────────────────┘三、核心实现
1. Mock 开关设计
文件:src/api/strategy-workbench/index-new.ts
typescript
/** 当前模块是否使用 Mock 数据(true=Mock模式, false=真实API) */
const IS_USE_MOCK = true;设计要点:每个模块独立控制开关,支持环境变量配置
2. 延迟函数(模拟网络请求)
typescript
/** 延迟函数,用于模拟网络延迟 */
function delay(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}3. Transform 数据转换层
typescript
/**
* 后端策略列表数据 -> 前端数据格式
* @param backendData 后端返回的原始数据
*/
function transformStrategyList(backendData: any): {
list: StrategyItem[];
total: number;
} {
return {
list: (backendData.records || backendData.list || []).map(
(item: any) => ({
id: String(item.id || item.strategyId), // 字段名适配
name: item.strategyName || item.name, // 字段名适配
// ... 其他字段映射
}),
),
total: backendData.total || 0,
};
}设计要点:Transform 层负责处理后端返回数据与前端 Mock 数据的字段差异
4. API 方法封装
typescript
/**
* 获取策略列表
* @param params 查询参数
*/
export async function getStrategyList(params?: {
page?: number;
pageSize?: number;
tradeType?: string;
status?: string;
keyword?: string;
}): Promise<{ list: StrategyItem[]; total: number }> {
// Mock 模式
if (IS_USE_MOCK) {
await delay(300); // 模拟网络延迟
const mockData = generateMockData();
return {
list: mockData,
total: mockData.length,
};
}
// 真实 API 模式
const response = await requestClient.get('/strategy/list', { params });
return transformStrategyList(response); // 数据转换
}5. 工具方法导出
typescript
// 重新导出 mock.ts 中的工具方法,供页面使用
export {
generateCurveData,
getTradeCycleText,
getTradeTypeText,
// ... 其他工具方法
} from './mock';设计要点:页面只需从
index.ts导入,无需关心数据来源
四、页面层改造
改造前
typescript
import { generateMockData } from '#/api/strategy-workbench/mock';
onMounted(() => {
strategyList.value = generateMockData(); // 直接调用 Mock
});改造后
typescript
import { getStrategyList } from '#/api/strategy-workbench/index';
// 加载策略列表
const loadingList = ref(false);
async function loadStrategyList() {
loadingList.value = true;
try {
const result = await getStrategyList(); // 调用 API 方法
strategyList.value = result.list;
// ...
} catch (error) {
console.error('加载策略列表失败:', error);
message.error('加载策略列表失败');
} finally {
loadingList.value = false;
}
}
onMounted(() => {
loadStrategyList();
});五、切换流程
从 Mock 切换到真实 API
只需一步:修改 IS_USE_MOCK = false
typescript
// 修改前
const IS_USE_MOCK = true;
// 修改后
const IS_USE_MOCK = false;后端接口对接时
- 确认接口路径:修改
requestClient.get('/strategy/list')中的路径 - 编写 Transform:根据后端实际返回字段,完善
transformStrategyList方法 - 关闭 Mock 开关:
IS_USE_MOCK = false
六、最佳实践
1. Mock 数据设计原则
- Mock 数据结构应与前端类型定义一致
- Mock 数据应覆盖各种场景(正常、空数据、边界情况)
2. Transform 层设计原则
- 清洗后端字段以符合前端接口定义
- 处理字段名差异(后端
strategyId→ 前端id) - 处理数据结构差异(后端
records→ 前端list) - 提供默认值,防止字段缺失导致报错
3. API 方法设计原则
- 统一返回类型,Mock 和真实 API 返回相同结构
- 支持参数传递,便于后期对接真实接口
- 添加适当的延迟,模拟真实网络环境
4. 类型安全
- 使用 TypeScript 类型定义
- Transform 方法返回类型应与 Mock 数据类型一致
七、优势总结
| 特性 | 说明 |
|---|---|
| 前端独立开发 | 不依赖后端接口,可并行开发 |
| 一键切换 | 只需修改一个布尔值 |
| 零页面改动 | 切换时页面代码无需修改 |
| 类型安全 | TypeScript 类型保障 |
| 数据适配 | Transform 层灵活适配后端数据 |
| 模块化 | 每个业务模块独立控制 |
AI 提示词模板 - 前端 API 层 Mock 开关设计
一、基础版提示词(适用于简单场景)
我现在的页面直接使用 Mock 数据,想改造为从 API 层引入数据请求方法。
后端接口还没开发好,需要先使用 Mock 数据替代。
后期接口开发完成后,希望能最小化改动切换到真实 API。
请帮我设计 API 层架构,要求:
1. 页面只从 API 层导入方法,不直接调用 Mock
2. 通过开关控制 Mock/真实 API 模式
3. 提供 Transform 方法适配后端数据格式二、完整版提示词(推荐使用)
## 背景
我正在开发一个 Vue3 + TypeScript 项目,前端页面需要使用后端 API。
当前页面直接调用 Mock 数据,后端接口尚未开发完成。
希望改造为从统一的 API 层获取数据,通过开关控制使用 Mock 还是真实 API。
## 现有代码结构
- 页面文件:`src/views/xxx/index.vue`
- Mock 数据:`src/api/xxx/mock.ts`
- 类型定义:`src/views/xxx/types.ts`
## 需求
1. 创建 API 统一入口文件 `src/api/xxx/index.ts`
2. 在 API 入口中实现 Mock 开关(IS_USE_MOCK),后期切换只需修改开关,无需改动页面代码。
3. Mock 数据 (激活状态):在请求方法内,使用 await delay(ms) 模拟延迟。直接返回mock数据
4. 变量统一:Mock 返回的数据必须赋值给一个名为 response 的变量。
5.逻辑复用:后续的业务逻辑(如判断 code === 200、Toast 提示)必须基于这个 response 变量编写,确保未来切换到真实接口时,只需解开注释即可,无需修改逻辑代码。 根据返回值和当前已有代码,写出transform方法,并应用到请求方法上。
6.transform 方法用于真实接口联调时调用。
7. API 方法封装,同时支持 Mock 和真实 API 调用
8. 页面层改造,从 API 入口导入方法,不直接使用 Mock
## 参考实现
/** 获取策略列表 */
export async function getStrategyList(params?: {
page?: number;
pageSize?: number;
tradeType?: string;
status?: string;
keyword?: string;
}): Promise<{ list: StrategyItem[]; total: number }> {
if (IS_USE_MOCK) {
await delay(300);
const mockData = generateMockData();
const response = { list: mockData, total: mockData.length };
return response;
}
// 真实 API 模式
const response = await requestClient.get('/strategy/list', { params });
return transformStrategyList(response);
}
请帮我实现以上改造,并说明切换到真实 API 时需要修改的内容。后端联调
提示词
## 核心任务
请根据我提供的【API 接口文档】以及现有的【前端 API 文件代码】,帮我重构并完善该 API 文件,使其能够完美对接真实后端接口。
# 约束与规范(严格遵守)
1. **接口路径**:请将 API 请求路径修改为后端提供的正式接口路径(如 `/strategy/list`),并确保请求方法(GET/POST)正确。
2. **关闭 Mock**:将代码中的 `IS_USE_MOCK` 开关设置为 `false`,如果可以,请清理掉冗余的 mock 数据生成函数(如 `generateMockData`)。
3. **字段映射 (Transform)**:真实后端的返回字段可能与前端现有的数据结构不一致。请在现有的 `transform` 方法中,将后端返回的字段(如 `strategyName`, `createTime` 等)精准映射到前端 Vue 组件依赖的字段(如 `name`, `createdAt` 等)。
4. **统一返回值**:标准化结构,绝对不能破坏现有的外层逻辑。
5. **异常兜底**:在 `transform` 处理中,做好空值判断和默认值兜底(例如 `res.data?.list || []`)。
# 输入信息
【API 接口文档 / Swagger JSON / 截图提取文本】
(在这里粘贴后端提供的接口 URL、请求方式、入参说明和出参 JSON 示例)
【参照现有前端 API 代码】
// transform 方法的设计原则是:输入后端原始数据,输出前端需要的数据结构。这样可以确保无论后端数据结构如何变化,我们都可以通过调整 transform 方法来适配,而不需要修改业务逻辑代码。
/**
* 转换策略列表接口返回的数据结构
* @param res 后端原始响应数据
* @returns 前端需要的策略列表数据结构
*/
export function transformStrategyList(res: any): { list: StrategyItem[]; total: number } {
if (res && res.code === 200) {
return {
// 如果对象数组中后端字段名称与前端使用的字段不匹配,在此处进行转换
list: res.data?.records || res.data?.list || [],
total: res.data?.total || 0,
};
}
return { list: [], total: 0 };
}
/**
* 1. 获取策略列表接口
* @param params 查询参数,包括颗粒度对应的点数、分页信息和搜索关键词等
* @returns 包含策略列表和总数的对象
* @description 根据 IS_USE_MOCK 开关决定是返回 Mock 数据还是调用真实 API。真实 API 模式下,通过 transformStrategyList 方法将后端原始数据转换为前端需要的数据结构。
*/
export async function getStrategyList(params?: {
points?: number; // 颗粒度对应的点数
page?: number;
pageSize?: number;
keyword?: string;
}): Promise<{ list: StrategyItem[]; total: number }> {
if (IS_USE_MOCK) {
await delay(300);
const mockData = generateMockData(params?.points ?? 24);
// 变量统一:直接赋值为业务最终需要的结构,不再经过 transform
const response = {
list: mockData,
total: mockData.length,
};
return response;
}
// 真实 API 模式
const response = await requestClient.get('/strategy/list', { params });
return transformStrategyList(response);
}
请直接输出重构后完整的 TypeScript API 文件代码,并在关键映射处加上简短的注释。