Skip to main content

Mock 数据

前端经常需要先 mock 数据开发,原因:

  • 后端接口未就绪,并行开发提速
  • 接口不稳定或文档不全
  • 自测边界场景(异常、分页为空、网络错误等)

方案选型

方案适用场景优点缺点
Mock.js纯前端拦截零配置、随机数据生成拦截 axios 不优雅,类型推导麻烦
MSW (Mock Service Worker)推荐真实网络层拦截、支持 Service Worker 和 Node学习成本略高
本地 Mock 服务(Koa/Express)后端主导、复杂场景完全自定义、可对接真实数据库需要单独起服务
Apifox / Apipost / Postman Mock联调阶段团队协作、文档一体化强依赖外网

方案一:MSW(推荐)

基于 Service Worker 拦截 fetch/axios 请求,生产代码零侵入

pnpm add msw -D
npx msw init public/ --save

定义 handler:

// src/mocks/handlers.ts
import { http, HttpResponse } from "msw";

export const handlers = [
http.get("/api/user", () => {
return HttpResponse.json({
code: 0,
data: { id: 1, name: "Lucas" },
});
}),

http.post("/api/login", async ({ request }) => {
const body = await request.json();
if (body.username === "admin") {
return HttpResponse.json({ code: 0, token: "xxx" });
}
return HttpResponse.json({ code: 1001, message: "用户名或密码错误" }, { status: 401 });
}),
];

启动 worker:

// src/mocks/browser.ts
import { setupWorker } from "msw/browser";
import { handlers } from "./handlers";

export const worker = setupWorker(...handlers);
// src/main.tsx
async function bootstrap() {
if (import.meta.env.DEV) {
const { worker } = await import("./mocks/browser");
await worker.start();
}
// ...渲染应用
}
bootstrap();

方案二:Mock.js + 本地服务

适合需要 mock 复杂数据生成(图片、随机文本、电话号等)的场景。

pnpm add mockjs koa koa-router koa-bodyparser -D
// mock/server.js
const Koa = require("koa");
const router = require("koa-router")();
const bodyParser = require("koa-bodyparser");
const Mock = require("mockjs");

const app = new Koa();
app.use(bodyParser());

router.get("/api/list", (ctx) => {
ctx.body = Mock.mock({
"list|10": [{ "id|+1": 1, name: "@cname", avatar: "@image" }],
});
});

app.use(router.routes()).listen(3001);

package.json 增加脚本:

"scripts": {
"mock": "nodemon mock/server.js"
}

实战建议

  1. 联调时逐步关停:通过环境变量 VITE_USE_MOCK=true 控制,避免上线时还走 mock
  2. TypeScript 类型同步:mock 返回的数据结构应该和后端约定一致,沉淀 .d.ts 文件供前后端共享
  3. 复杂状态用真实 DB:涉及关联查询、事务的业务场景,本地起个 SQLite 比手写 mock 强
  4. 错误码覆盖:mock 至少要覆盖成功、参数错误、未授权、服务异常 4 类