安装依赖
安装Mockjs
和vite-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
文件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
整体的请求函数返回类型,例如:200
、500
的不同状态
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
文件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
内部没有做baseURL
,mockjs
的basuURL
就是本地的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
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>
POST、GET请求参数以及请求头信息获取
用户在请求接口的时候可能会传id
、name
等参数查询信息,这个时候需要在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
的时候会感觉一个接口写了两遍,绕来绕去的,实际上是你一个人模拟了两个角色在操作。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。