Mockjs:项目实战,以 “用户管理系统” 为例,展示如何在实际开发中使用 Mock.js 模拟后端接口,实现独立开发与测试

以下是一个基于 Mock.js 的前端项目实战案例,以 “用户管理系统” 为例,展示如何在实际开发中使用 Mock.js 模拟后端接口,实现独立开发与测试。

项目背景

假设我们需要开发一个用户管理系统,包含用户列表查询用户详情查看新增用户删除用户四个核心功能。后端接口尚未开发完成,前端需基于接口文档用 Mock.js 模拟数据,先行开发页面与交互。

技术栈

  • 前端框架:Vue 3(或 React,思路一致)
  • 请求库:Axios
  • 模拟工具:Mock.js
  • UI 组件库:Element Plus(可选)

实战步骤

步骤 1:环境搭建

  1. 创建 Vue 项目并安装依赖:

    # 创建项目
    vue create mock-demo
    cd mock-demo
    
    # 安装依赖
    npm install axios mockjs --save
    npm install element-plus --save # 可选,用于快速搭建 UI
    
  2. 目录结构规划:

    src/
    ├── api/           # 接口请求封装
    │   └── user.js    # 用户相关接口
    ├── mock/          # Mock 配置
    │   └── userMock.js # 用户接口模拟规则
    ├── views/         # 页面组件
    │   └── UserManage.vue # 用户管理页面
    ├── main.js        # 入口文件(引入 Mock)
    

步骤 2:定义接口文档(模拟)

假设后端提供的接口文档如下:

接口功能请求地址方法请求参数响应格式
获取用户列表/api/usersGETpage(页码)、size(每页条数){ code: 200, data: { list: [], total: 100 } }
获取用户详情/api/users/:idGETid(用户 ID){ code: 200, data: { id, name, ... } }
新增用户/api/usersPOSTnameageemail{ code: 200, data: { id, ... } }
删除用户/api/users/:idDELETEid(用户 ID){ code: 200, message: "删除成功" }

步骤 3:编写 Mock 规则(src/mock/userMock.js

根据接口文档,用 Mock.js 定义模拟数据和请求拦截规则:

import Mock from 'mockjs';
import { param2Obj } from '../utils'; // 工具函数:解析 URL 参数(见下文)

// 模拟用户数据(全局变量,用于模拟“数据持久化”)
let userList = Mock.mock({
  'list|100': [{ // 初始生成 100 条用户数据
    'id|+1': 1, // 自增 ID
    'name': '@cname', // 中文姓名
    'age|18-60': 1, // 年龄 18-60
    'email': '@email', // 随机邮箱
    'gender|1': ['男', '女'], // 性别
    'phone': '@phone', // 手机号
    'address': '@city(true)', // 地址(省+市)
    'createTime': '@datetime("yyyy-MM-dd HH:mm:ss")' // 创建时间
  }]
}).list;

// 1. 拦截:获取用户列表(分页)
Mock.mock(/\/api\/users/, 'get', (options) => {
  // 解析请求参数(page、size)
  const { page = 1, size = 10 } = param2Obj(options.url);
  const startIndex = (page - 1) * size;
  const endIndex = startIndex + parseInt(size);
  
  // 模拟分页逻辑
  const mockList = userList.filter((_, index) => index >= startIndex && index < endIndex);
  return {
    code: 200,
    data: {
      list: mockList,
      total: userList.length // 总条数
    }
  };
});

// 2. 拦截:获取用户详情
Mock.mock(/\/api\/users\/(\d+)/, 'get', (options) => {
  // 从 URL 中提取 ID(如 /api/users/123 → 123)
  const id = parseInt(options.url.match(/\/api\/users\/(\d+)/)[1]);
  const user = userList.find(u => u.id === id);
  
  return user 
    ? { code: 200, data: user } 
    : { code: 404, message: '用户不存在' };
});

// 3. 拦截:新增用户
Mock.mock(/\/api\/users/, 'post', (options) => {
  // 解析请求体(新增用户的信息)
  const newUser = JSON.parse(options.body);
  // 生成新 ID(最大 ID + 1)
  const maxId = Math.max(...userList.map(u => u.id), 0);
  newUser.id = maxId + 1;
  newUser.createTime = Mock.mock('@datetime("yyyy-MM-dd HH:mm:ss")'); // 补充创建时间
  
  // 添加到用户列表
  userList.unshift(newUser); // 新增用户放最前面
  return { code: 200, data: newUser, message: '新增成功' };
});

// 4. 拦截:删除用户
Mock.mock(/\/api\/users\/(\d+)/, 'delete', (options) => {
  const id = parseInt(options.url.match(/\/api\/users\/(\d+)/)[1]);
  const index = userList.findIndex(u => u.id === id);
  
  if (index !== -1) {
    userList.splice(index, 1); // 从列表中删除
    return { code: 200, message: '删除成功' };
  } else {
    return { code: 404, message: '用户不存在' };
  }
});

// 工具函数:解析 URL 参数为对象(如 ?page=1&size=10 → { page: '1', size: '10' })
export function param2Obj(url) {
  const search = url.split('?')[1];
  if (!search) return {};
  return JSON.parse(
    '{"' +
    decodeURIComponent(search)
      .replace(/"/g, '\\"')
      .replace(/&/g, '","')
      .replace(/=/g, '":"') +
    '"}'
  );
}

步骤 4:封装 API 请求(src/api/user.js

用 Axios 封装接口请求,与 Mock 拦截的地址对应:

import axios from 'axios';

// 1. 获取用户列表(分页)
export const getUserList = (page, size) => {
  return axios.get('/api/users', { params: { page, size } });
};

// 2. 获取用户详情
export const getUserDetail = (id) => {
  return axios.get(`/api/users/${id}`);
};

// 3. 新增用户
export const addUser = (userData) => {
  return axios.post('/api/users', userData);
};

// 4. 删除用户
export const deleteUser = (id) => {
  return axios.delete(`/api/users/${id}`);
};

步骤 5:在页面中使用(src/views/UserManage.vue

开发用户管理页面,调用 API 接口(实际会被 Mock 拦截):

<template>
  <div class="user-manage">
    <el-card>
      <div class="header">
        <h2>用户管理</h2>
        <el-button type="primary" @click="showAddDialog = true">新增用户</el-button>
      </div>

      <!-- 用户列表 -->
      <el-table :data="userList" border>
        <el-table-column prop="id" label="ID" width="80"></el-table-column>
        <el-table-column prop="name" label="姓名"></el-table-column>
        <el-table-column prop="age" label="年龄"></el-table-column>
        <el-table-column prop="gender" label="性别"></el-table-column>
        <el-table-column prop="email" label="邮箱"></el-table-column>
        <el-table-column prop="createTime" label="创建时间"></el-table-column>
        <el-table-column label="操作">
          <template #default="scope">
            <el-button @click="handleDetail(scope.row.id)">查看</el-button>
            <el-button type="danger" @click="handleDelete(scope.row.id)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <el-pagination
        :current-page="page"
        :page-size="size"
        :total="total"
        @current-change="handlePageChange"
      ></el-pagination>

      <!-- 新增用户弹窗 -->
      <el-dialog v-model="showAddDialog" title="新增用户">
        <el-form :model="newUser" label-width="80px">
          <el-form-item label="姓名">
            <el-input v-model="newUser.name"></el-input>
          </el-form-item>
          <el-form-item label="年龄">
            <el-input v-model.number="newUser.age"></el-input>
          </el-form-item>
          <el-form-item label="邮箱">
            <el-input v-model="newUser.email"></el-input>
          </el-form-item>
          <el-form-item label="性别">
            <el-radio-group v-model="newUser.gender">
              <el-radio label="男"></el-radio>
              <el-radio label="女"></el-radio>
            </el-radio-group>
          </el-form-item>
        </el-form>
        <template #footer>
          <el-button @click="showAddDialog = false">取消</el-button>
          <el-button type="primary" @click="handleAdd">确定</el-button>
        </template>
      </el-dialog>
    </el-card>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { getUserList, addUser, deleteUser } from '../api/user';
import { ElMessage } from 'element-plus';

// 分页参数
const page = ref(1);
const size = ref(10);
const total = ref(0);
const userList = ref([]);

// 新增用户弹窗
const showAddDialog = ref(false);
const newUser = ref({ name: '', age: 18, email: '', gender: '男' });

// 初始化加载用户列表
const loadUserList = async () => {
  try {
    const res = await getUserList(page.value, size.value);
    userList.value = res.data.data.list;
    total.value = res.data.data.total;
  } catch (err) {
    console.error('加载用户失败', err);
  }
};

// 分页切换
const handlePageChange = (newPage) => {
  page.value = newPage;
  loadUserList();
};

// 新增用户
const handleAdd = async () => {
  try {
    await addUser(newUser.value);
    ElMessage.success('新增成功');
    showAddDialog.value = false;
    newUser.value = { name: '', age: 18, email: '', gender: '男' }; // 重置表单
    loadUserList(); // 刷新列表
  } catch (err) {
    ElMessage.error('新增失败');
  }
};

// 删除用户
const handleDelete = async (id) => {
  try {
    await deleteUser(id);
    ElMessage.success('删除成功');
    loadUserList(); // 刷新列表
  } catch (err) {
    ElMessage.error('删除失败');
  }
};

// 查看详情(简化处理)
const handleDetail = (id) => {
  ElMessage.info(`查看 ID 为 ${id} 的用户详情`);
};

// 页面挂载时加载数据
onMounted(loadUserList);
</script>

<style scoped>
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}
</style>

步骤 6:在入口文件中引入 Mock(src/main.js

import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';

// 引入 Mock 配置(生产环境可注释掉)
import './mock/userMock';

createApp(App)
  .use(router)
  .use(ElementPlus)
  .mount('#app');

关键实现说明

  1. 数据持久化模拟:用全局变量 userList 存储用户数据,新增 / 删除操作直接修改该变量,模拟后端数据库的 “持久化” 效果,确保页面刷新后数据状态一致(实际开发中可结合 localStorage 进一步优化)。

  2. 动态参数处理:通过正则匹配 URL(如 /api/users/:id)和解析请求参数(pagesize),模拟真实接口的动态路由和分页逻辑。

  3. 业务逻辑模拟:模拟了 “用户不存在”“删除成功 / 失败” 等场景,使前端能完整测试各种交互流程。

  4. 环境隔离:Mock 配置仅在开发环境引入,生产环境可通过注释或环境变量控制,避免影响真实接口。

运行效果

启动项目后,即可在页面上:

  • 分页查看模拟的用户列表;
  • 点击 “新增用户” 提交表单,新增数据会实时显示在列表;
  • 点击 “删除” 按钮移除用户,列表自动刷新;
  • 所有操作均无需后端接口,完全由 Mock.js 模拟响应。

总结

通过 Mock.js,前端可以在后端接口就绪前独立完成页面开发、交互逻辑和边界场景测试,大幅提升前后端并行开发效率。实际项目中,可根据接口文档扩展更多 Mock 规则(如异常状态码、复杂嵌套数据等),进一步贴近真实业务场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

canjun_wen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值