前后端分离,使用MOCK进行数据模拟开发,让前端攻城师独立于后端进行开发

mock是什么

Mock生成随机数据,拦截Ajax 请求,前后端分离,让前端攻城师独立于后端进行开发。 增加单元测试的真实性 通过随机数据,模拟各种场景。
在实际开发过程中,前端是通过axios来请求数据的,很多时候前端开发者就是通过写固定的JSON数据来模拟数据,但是这个JSON是一个对象,没有经过数据请求的情况下直接使用,在后续的工作中要等到后端将API写好以后再进行对接API,而mock就是通过拦截真实的axios的请求来模拟数据,相当于通过mock写一个假的API,并直接拿来使用,前端开发人员是可以真实的写一个axios请求的
简单来说,mock就是假的API

(一)前提条件

vue项目已经进行了axios请求接口封装,可以正常的请求后端接口(我用的是登录接口测试是合适的)。

(二)安装

我使用的是vue的vite(Vue3的)框架。使用的依赖是以下两个依赖。

"vite-plugin-mock": "^2.9.6",
"mockjs": "^1.1.0",

(三)配置

vite.config.js 文件中引入并配置这个插件:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { viteMockServe } from 'vite-plugin-mock'

export default defineConfig({
  plugins: [
    vue(),
   viteMockServe({
    ignore: /^\_/,
    mockPath: 'mock',
    localEnabled: !isBuild,//表示是否在本地环境中启用Mock服务器。如果isBuild为false,则localEnabled为true,表示在本地环境中启用Mock服务器;反之亦然。
    prodEnabled: isBuild,//表示是否在生产环境中启用Mock服务器。如果isBuild为true,则prodEnabled为true,表示在生产环境中启用Mock服务器;反之亦然。
    injectCode: `
      import { setupProdMockServer } from '../mock/_createProductionServer';

      setupProdMockServer();
      `,
  }),
  ],
})

创建mock服务
其中**/mock/_createProductionServer**文件如下:

import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer';

const modules = import.meta.glob('./**/*.ts', { eager: true });

const mockModules: any[] = [];
Object.keys(modules).forEach((key) => {
  if (key.includes('/_')) {
    return;
  }
  mockModules.push(...(modules as Recordable)[key].default);
});

/**
 * Used in a production environment. Need to manually import all modules
 */
export function setupProdMockServer() {
  createProdMockServer(mockModules);
}

(四)实例

1、在mock文件夹中的一个house.ts文件:

import { MockMethod } from 'vite-plugin-mock';
import { resultPageSuccess, resultSuccess, baseUrl } from '../_util';


const testList = (() => {
  const result: any[] = [];
  for (let index = 0; index < 40; index++) {
    result.push({
      id: index,
      apartment: '@integer(1,4)',//公寓楼--字典
      building: '@integer(1,10)',//栋数--字典
      room: '@integer(1,32)' + '0' + '@integer(1,9)' + '-' + '@integer(1,6)',// 房间--string
      type: '@integer(1,4)',//户型--字典
      address: "@county(true)", // 地址--string
      area: '@integer(15,90)',//面积--数字
      status: '@integer(1,2)',// 入住状态--字典
      matching: "@ctitle",//房屋配套---string
      decorationTime: "@date(yyyy-MM-dd)", //装修时间--data
      checkDate: "@date(yyyy-MM-dd)", // 预入住时间---data
      rent: "@float(500,4000,0,2)",//租金---float
      managerId: "admin",// 用户(公寓管理员)标识--用户列表中的username字段---根据实际情况定是否使用该字段
      managerName: "@cname",//用户名称(公寓管理员)---后端根据用户标识匹配返回前端
      pictureList: "@image", // 多张图片
      remarks: "@ctitle", // 备注信息---富文本
      identityCard: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/,//身份证号码-----number
      phone: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,//生成的符合正则表达式的字符串
      identificationPhoto: "@image(35x50)", // 证件照--一张图片
    });
  }
  return result;
})();

const info = (() => {
  const result = {
    id: 1,
    apartment: '2',
    building: '9',
    room: '@integer(1,32)' + '0' + '@integer(1,9)' + '-' + '@integer(1,6)',
    type: '4',
    address: "@county(true)",
    area: '@integer(15,90)',
    status: '1',
    matching: "@ctitle",
    decorationTime: "@date(yyyy-MM-dd)",
    checkDate: "@date(yyyy-MM-dd)",
    rent: "@float(500,4000,0,2)",
    managerId: "admin",
    managerName: "@cname",
    pictureList: "@image",
    remarks: "@ctitle",
  }
  return result;
})();

export default [
  {
    url: `${baseUrl}/internetOfThings/getHouseList`,
    timeout: 1000,
    method: 'get',
    response: ({ query }) => {
      const { page = 1, pageSize = 20 } = query;
      return resultPageSuccess(page, pageSize, testList);
    },
  },
  {
    url: `${baseUrl}/internetOfThings/getHouseInfo`,
    timeout: 1000,
    method: 'get',
    response: () => {
      return resultSuccess(info);
    },
  },
] as MockMethod[];

其中_util.ts文件:

export function resultSuccess<T = Recordable>(result: T, { message = 'ok' } = {}) {
  return {
    code: 0,
    result,
    message,
    type: 'success',
  };
}

export function resultPageSuccess<T = any>(
  pageNo: number,
  pageSize: number,
  list: T[],
  { message = 'ok' } = {}
) {
  const pageData = pagination(pageNo, pageSize, list);

  return {
    ...resultSuccess({
      records: pageData,
      total: list.length,
    }),
    message,
  };
}

export function resultError(message = 'Request failed', { code = -1, result = null } = {}) {
  return {
    code,
    result,
    message,
    type: 'error',
  };
}

export function pagination<T = any>(pageNo: number, pageSize: number, array: T[]): T[] {
  const offset = (pageNo - 1) * Number(pageSize);
  const ret =
    offset + Number(pageSize) >= array.length
      ? array.slice(offset, array.length)
      : array.slice(offset, offset + Number(pageSize));
  return ret;
}

export interface requestParams {
  method: string;
  body: any;
  headers?: { authorization?: string };
  query: any;
}

/**
 * @description 本函数用于从request数据中获取token,请根据项目的实际情况修改
 *
 */
export function getRequestToken({ headers }: requestParams): string | undefined {
  return headers?.authorization;
}

//TODO 接口父路径(写死不够灵活)
export const baseUrl = '/api/mock';

2、mock API书写

就像平时请求API的接口一样正常请求数据,defHttp 是封装好的axios请求封装好的函数,没有做其他操作。

import { defHttp } from '/@/utils/http/axios';


enum Api {
  houseList = '/mock/internetOfThings/getHouseList',
  houseInfo = '/mock/internetOfThings/getHouseInfo',
}

/**
 * @description: 房源管理--列表
 */

export const getHouseList = (params) => {
  // console.log(params,"API传参");
  return defHttp.get({ url: Api.houseList, params });
}
/**
 * 详情
 * */
export const getHouseInfo = (id) => {
  return defHttp.get({ url: Api.houseInfo, id });

}

3、API的实际使用

  getHouseList(recordId.value).then((res) => {
     console.log(res, '请求数据');
    });

(五)效果

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值