Skip to content
页面导航
精简

前端 API 层 Mock 开关设计方案 - 方法总结

一、背景与目标

问题场景

  • 前端页面开发时,后端接口尚未开发完成
  • 需要使用 Mock 数据进行前端开发和测试
  • 后期接口开发完成后,需要最小化改动切换到真实 API

核心目标

  1. 前端先行:不依赖后端接口,可独立开发
  2. 平滑切换:Mock → 真实 API 切换只需修改一个开关
  3. 最小改动:切换时前端页面代码无需修改
  4. 数据适配:通过 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;

后端接口对接时

  1. 确认接口路径:修改 requestClient.get('/strategy/list') 中的路径
  2. 编写 Transform:根据后端实际返回字段,完善 transformStrategyList 方法
  3. 关闭 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 文件代码,并在关键映射处加上简短的注释。