头图

安装依赖

安装Mockjsvite-plugin-mock

pnpm install mockjs vite-plugin-mock@2.9.6 -D
如果启动项目终端报错:mock error: Package subpath './es/createProdMockServer' is not defined by "exports" 说明你的版本可能有问题,应该把mockjs切到2.9.6的版本

在vite.config.ts内配置插件

import { defineConfig, loadEnv } from "vite";
import { viteMockServe } from "vite-plugin-mock";

// 省略其它配置...

// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
   // 根路径
   const root = process.cwd();
   // 获取跟路径对应的文件
   const env: any = loadEnv(mode, root);
  
    // 插件
    plugins: [
      viteMockServe({
        mockPath: "./src/mock/", // 目录位置
        logger: true, //  是否在控制台显示请求日志
        supportTs: true, // 是否读取ts文件模块
        localEnabled: env.VITE_APP_OPEN_MOCK === "true", // 设置是否启用本地mock文件
        prodEnabled: env.VITE_APP_OPEN_MOCK === "true", // 设置打包是否启用mock功能
        // 这样可以控制关闭mock的时候不让mock打包到最终代码内
        injectCode: `
            import { setupProdMockServer } from '../src/mock/index';
            setupProdMockServer();
          `
      })
  ];

  // 省略其它配置...
  
});

创建mockjs服务

创建mock文件夹,在mock文件夹内新建index.ts文件
image.png
image.png
mock/index.ts文件内容:

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

// 引入test文件,该文件还没创建,在下面内容会说明
import testModule from "./test/index";

// 创建mock服务
export function setupProdMockServer() {
  createProdMockServer([...testModule,]);
}

新建mockjs返回格式封装函数,路径:mock/_utils.ts
该文件主要用于控制mockjs整体的请求函数返回类型,例如:200500的不同状态
image.png

import Mock from "mockjs";

/** 返回成功数据 */
export const resultSuccess = (data: unknown) => {
  return Mock.mock({
    code: 200,
    data,
    message: "请求成功",
    success: true
  });
};

/** 返回失败数据 */
export const resultError = (data: unknown, message: string, code = 500) => {
  return Mock.mock({
    code,
    data,
    message,
    success: false
  });
};

mock文件夹内创建test文件夹,并新建index.ts文件
image.png
test/index.ts文件内容:

import type { MockMethod } from "vite-plugin-mock";
import { resultSuccess, resultError } from "../_utils";

// 创建mockjs接口服务
export default [
  {
    url: "/mock/test/success", // API接口
    method: "get", // get请求
    timeout: 300, // 请求时长
    response: () => {
      // 返回请求结果
      return resultSuccess("SnowAdmin开源免费,Welcome!");
    }
  },
  {
    url: "/mock/test/fail", // API接口
    method: "get", // get请求
    timeout: 300, // 请求时长
    response: () => {
      // 返回请求结果
      return resultError(null, "模拟mock数据出错", 500);
    }
  }
] as MockMethod[];

封装axios请求

封装axios请求,这里我只做一个简单的示例,主要是baseURL这里需要注意,mockjs是不需要走Proxy代理的

import axios from "axios";
import router from "@/router";
import { Message } from "@arco-design/web-vue";

// 是否开启本地mock,在.env文件内配置
const MOCK_FLAG = import.meta.env.VITE_APP_OPEN_MOCK === "true";

// 创建axios实例
const service = axios.create({
  baseURL: MOCK_FLAG ? "" : "/api"
});
// 请求拦截器
service.interceptors.request.use(
  function (config: any) {
    // 发送请求之前做什么
    // 获取token鉴权
    let userInfo: any = {};
    if (localStorage.getItem("user-info")) {
      userInfo = JSON.parse(localStorage.getItem("user-info") as string);
    }
    if (userInfo?.token) {
      // 有token,在请求头中携带token
      config.headers.Authorization = userInfo.token;
    }
    return config;
  },
  function (error: any) {
    // 请求错误
    return Promise.reject(error);
  }
);

// 响应拦截器
service.interceptors.response.use(
  function (response: any) {
    if (response.status != 200) {
      Message.error("服务器异常,请联系管理员");
      return Promise.reject(response.data);
    }
    let res = response.data;
    if (res.code == 401) {
      Message.error("登录状态已过期");
      router.push("/login");
      return Promise.reject(res);
    } else if (res.code == 404) {
      Message.error("请求连接超时");
      return Promise.reject(res);
    } else if (res.code != 200) {
      Message.error(res.message);
      return Promise.reject(res);
    } else {
      // 返回数据
      return Promise.resolve(res);
    }
  },
  function (error: any) {
    localStorage.removeItem("token");
    router.push("/login");
    return Promise.reject(error);
  }
);
export default service;

vite.config.ts请求配置

由于mockjs走的是本地请求,所以不需要代理,在axios内部没有做baseURLmockjsbasuURL就是本地的localhost

import { defineConfig, loadEnv } from "vite";
import path from "path";

// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
  // 根路径
  const root = process.cwd();
  // 获取跟路径对应的文件
  const env: any = loadEnv(mode, root);
  return {
    server: {
      host: "0.0.0.0",
      open: true,  // 启动项目自动打开浏览器
      // 为开发服务器配置自定义代理规则-用于开发时的代理
      proxy: {
        // 由于mockjs走的是本地请求,所以不需要代理,在axios内部没有做baseURL
        "/api": {
          target: env.VITE_APP_BASE_URL,
          changeOrigin: true,
          rewrite: path => path.replace(/^\/api/, "")
        }
      }
    },

    // 省略其它配置...
  };
});

axios请求接口

创建axios的具体请求,api文件夹内创建test文件夹,内部创建index.ts
image.png

import axios from "@/api";

// 这个接口的url对应的就是mockjs接口服务
export const mockTestAPI = () => {
  return axios({
    url: "/mock/test/success",
    method: "get"
  });
};

页面调用验证请求

随便找个页面验证请求

<script setup lang="ts">
import { mockTestAPI } from "@/api/modules/test/index";

const getInfo = async () => {
  let res = await mockTestAPI();
  console.log("请求结果", res);
};
getInfo();
</script>

image.png

POST、GET请求参数以及请求头信息获取

用户在请求接口的时候可能会传idname等参数查询信息,这个时候需要在mockjs的请求服务中获取用户参数
post请求参数在response中解构body获取
get请求参数在response中解构query获取
● 请求头信息在response中解构headers获取

import type { MockMethod } from "vite-plugin-mock";
import { resultSuccess, resultError } from "../_utils";

// post请求body,get请求query
export default [
  {
    url: "/mock/login",
    method: "post",
    timeout: 300,
    response: ({ body }: any) => {
       // body 携带的参数信息
    }
  },
   {
    url: "/mock/user/address",
    method: "get",
    timeout: 300,
    response: ({ query }: any) => {
       // query 携带的参数信息
    }
  },
  {
    url: "/mock/user/info",
    method: "get",
    timeout: 300,
    response: ({ headers }: any) => {
      // headers 请求头信息
    }
  }
] as MockMethod[];

最后我要告诉大家,mockjs你可以看成是运行在服务器端的,你在配置mockjs时可以把自己想象成后端开发者,而axios是运行在前端的,你在写axios的时候把自己看成是前端开发者。一个请求接口,mockjs需要配置一遍,前端的axios也需要配置一遍,服务端的接口url需要跟axios端的接口url一致,你在用mockjs的时候会感觉一个接口写了两遍,绕来绕去的,实际上是你一个人模拟了两个角色在操作。


参考资料:
Mock.js官网
vite-plugin-mock


兔子先森
420 声望18 粉丝

致力于新技术的推广与优秀技术的普及。