文章目录
- 什么是Mock数据
- 使用Mock数据的优点
- Mock数据使用步骤
- 一、安装依赖mockjs、vite-plugin-mock
- 二、vite.config.ts 文件中配置
- 三、在根目录下创建mock文件
- 四、编写api接口调用文件
- 1、src文件夹下新建utils/request.ts
- 2、src文件夹下新建api/user.ts
- 五、业务页面调用
- 六、Mock的用法规则
- 七、在生产环境中的使用
- 1、创建mockProdServer.ts 文件
- 2、配置 vite-plugin-mock
- 3、注意事项
什么是Mock数据
Mock 可以翻译为“模拟”,在前端开发中通常指模拟后端接口和数据。
在软件开发过程中,Mock数据指的是一种虚拟的测试数据,用于模拟真实的数据情况。它可以用来替代真实的数据源,从而实现在没有真实数据的情况下进行开发和测试的需求。
我们在开发的时候,一般都是前后端同时开发,尤其是某些后台系统开发时,很多前端同学分分钟就可以做完静态页面的开发,然后就是摸鱼时间,等待后端的接口。如果你的后端同事非常配合,愿意在设计数据库的时候顺便定好返回的数据结构和字段,并且联调时间很紧张的时候,这时候你应该考虑着手去做一下前端 mock,为联调争取时间。
Mock数据的使用不仅可以提高开发效率,还可以避免与真实数据源的依赖性,减少开发过程中的等待时间,以及降低测试环境的复杂性。
使用Mock数据的优点
简单性:不需要复杂的配置和部署过程,可以快速地创建和管理模拟数据。
灵活性:可以满足不同的开发需求,例如支持不同的请求类型、不同的请求方式等。
真实性:能够生成更接近真实的数据,可以模拟不同的数据类型、格式和结构。
维护性:可以方便地更新和修改模拟数据。
合作性: 可以在团队内方便的共享模拟数据。
Mock数据使用步骤
一、安装依赖mockjs、vite-plugin-mock
提供本地和生产模拟服务。
vite 的数据模拟插件,是基于 vite.js 开发的。 并同时支持本地环境和生产环境。 Connect 服务中间件在本地使用,mockjs 在生产环境中使用。
npm i mockjs vite-plugin-mock --save-dev
二、vite.config.ts 文件中配置
// vite.config.ts
import { defineConfig } from 'vite'
import { viteMockServe } from 'vite-plugin-mock'
import vue from '@vitejs/plugin-vue'
export default defineConfig(({ command }) => {
return {
plugins: [
vue(),
viteMockServe({
mockPath: 'mock', // mock文件夹路径
enable: command === 'serve' // 只有开发环境才开启mock
}),
],
}
})
- viteMockServe 配置
{
mockPath?: string;
ignore?: RegExp | ((fileName: string) => boolean);
watchFiles?: boolean;
enable?: boolean;
ignoreFiles?: string[];
configPath?: string;
logger?:boolean;
}
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
mockPath | string | mock | 设置模拟.ts 文件的存储文件夹 |
ignore | RegExp | undefined | 自动读取模拟.ts 文件时,请忽略指定格式的文件 |
watchFiles | boolean | true | 设置是否监视mockPath对应的文件夹内文件中的更改 |
enable | boolean | true | 是否启用 mock 功能 |
configPath | string | vite.mock.config.ts | 设置模拟读取的数据条目 |
logger | boolean | true | 是否在控制台显示请求日志 |
三、在根目录下创建mock文件
项目文件夹下新建mock文件夹,用于存放本地mock文件
// mock/user.ts
const createUserList = () => {
return [
{
userId: 1,
avatar: 'https://pic1.zhimg.com/80/v2-083faf550543c1e9f134b56b3322ee3c_720w.webp',
username: 'admin',
password: '123456789',
desc: '下船不谈船里事',
roles: ['平台管理员'],
buttons: ['cuser.detail'],
routes: ['home'],
token: 'Admin Token'
},
{
userId: 2,
avatar: 'https://pic1.zhimg.com/80/v2-e1427f6a21122ac163ff98d24f55d372_720w.webp',
username: 'system',
password: '123456789',
desc: '旧人不谈近况,新人不讲过往',
roles: ['系统管理员'],
buttons: ['cuser.detail', 'cuser.user'],
routes: ['home'],
token: 'Admin Token'
}
]
}
export default [
// 用户登录接口
{
url: '/api/user/login',
method: 'post',
response: ({ body }: any) => {
// 获取请求体携带过来的用户名与密码
const { username, password } = body
// 调用获取用户信息函数,用于判断是否有此用户
const checkUser = createUserList().find(
(item) => item.username === username && item.password === password
)
// 没有用户则返回失败信息
if (!checkUser) {
return {
code: 201,
data: {
message: '账号或者密码不正确'
}
}
}
// 如果有返回成功信息
const { token } = checkUser
return {
code: 200,
data: {
token
}
}
}
},
// 获取用户信息接口
{
url: '/api/user/info',
method: 'get',
response: (request: any) => {
// 获取请求头携带的 token
const token = request.headers.token
// 查看用户信息数据中是否包含有此 token 的用户
const checkUser = createUserList().find((item) => item.token === token)
// 没有就返回失败信息
if (!checkUser) {
return {
code: 201,
data: {
message: '获取用户信息失败'
}
}
}
// 有就返回成功信息
return {
code: 200,
data: {
checkUser
}
}
}
}
]
四、编写api接口调用文件
1、src文件夹下新建utils/request.ts
// utils/request.ts
import axios from "axios";
//创建一个axios实例
const request = axios.create({
baseURL: '',
timeout: 20000,
});
// 添加请求拦截器
request.interceptors.request.use(
function (config) {
// 请求地址携带时间戳
const _t = new Date().getTime()
config.url += `?${_t}`
// 请求头携带token
config.headers['token'] = localStorage.getItem('token') || ''
// 在发送请求之前做些什么
// console.log('我要准备请求啦------')
// console.log(config, '请求配置')
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加响应拦截器
request.interceptors.response.use(
function (response) {
// 对响应数据做点什么
// console.log('我接收到响应数据啦------')
// console.log(response, '响应配置')
if (response.status === 200) {
return Promise.resolve(response.data)
} else {
return Promise.reject(response)
}
},
function (error) {
// 对响应错误做点什么
if (error && error.response) {
switch (error.response.status) {
case 400:
error.message = '错误请求';
break;
case 401:
error.message = '未授权,请重新登录';
break;
case 403:
error.message = '拒绝访问';
break;
case 404:
error.message = '请求错误,未找到该资源';
break;
case 405:
error.message = '请求方法未允许';
break;
case 408:
error.message = '请求超时';
break;
case 500:
error.message = '服务器端出错';
break;
case 501:
error.message = '网络未实现';
break;
case 502:
error.message = '网络错误';
break;
case 503:
error.message = '服务不可用';
break;
case 504:
error.message = '网络超时';
break;
case 505:
error.message = 'http版本不支持该请求';
break;
default:
error.message = `未知错误${error.response.status}`;
}
} else {
error.message = "连接到服务器失败";
}
return Promise.reject(error);
}
);
/*
* get请求:从服务器端获取数据
* url:请求地址
* params:参数
* */
export function get(url:string, params = {}) {
return new Promise((resolve, reject) => {
request({
url: url,
method: 'get',
params: params
}).then(response => {
resolve(response);
}).catch(error => {
reject(error);
});
});
}
/*
* post请求:向服务器端提交数据
* url:请求地址
* params:参数
* */
export function post(url:string, params = {}) {
return new Promise((resolve, reject) => {
request({
url: url,
method: 'post',
data: params
}).then(response => {
resolve(response);
}).catch(error => {
reject(error);
});
});
}
// 对外暴露请求方法
export default {
get,
post
}
2、src文件夹下新建api/user.ts
// api/user.ts
import { get, post } from './request';
const api = {
login: '/api/user/login',
users: '/api/user/info'
}
//登录
export const login = (params: any) => {
return post(api.login, params).then((res: any) => {
if (res.code === 200) {
localStorage.setItem('token', res.data.token);
}
return Promise.resolve(res);
})
}
//获取用户信息
export const getUserInfo = () => {
const token = localStorage.getItem('token');
if (!token) return Promise.reject(new Error('用户未登录'));
return get(api.users);
}
五、业务页面调用
// App.vue
import { onBeforeMount } from 'vue'
import {login,getUserInfo} from "./utils/user"
onBeforeMount(async () => {
// 登录
const user = await login({
username: 'admin',
password: '123456789'
})
console.log(user)
// 获取用户信息
const users = await getUserInfo()
console.log(users)
})
六、Mock的用法规则
import mockJS from 'mockjs'
const userList = mockJS.mock({
// 属性 list 的值是一个数组,其中含有 1 到 10 个元素
'list|1-10': [
{
// 随机生成id号
id: '@id',
// 随机生成中文姓名
name: '@cname',
// 属性 id 是一个自增数,起始值为 1,每次增 1
'id|+1': 1,
// 随机生成ip地址
ip: '@ip',
// 随机生成省市区地址
address:'@county(true)',
// 随机生成邮政编码
zip:'@zip',
// 随机生成18-70之间的年龄
"age|18-70": 20,
// 随机生成日期
date: '@date("yyyy-MM-dd")',
// 随机生成头像
avatar:"@image('200x200')",
}
]
})
七、在生产环境中的使用
1、创建mockProdServer.ts 文件
// mockProdServer.ts
import { createProdMockServer } from 'vite-plugin-mock/client'
// 逐一导入您的mock.ts文件
// 如果使用vite.mock.config.ts,只需直接导入文件
// 可以使用 import.meta.glob功能来进行全部导入
import testModule from '../mock/test'
export function setupProdMockServer() {
createProdMockServer([...testModule])
}
2、配置 vite-plugin-mock
import { viteMockServe } from 'vite-plugin-mock'
import { UserConfigExport, ConfigEnv } from 'vite'
export default ({ command }: ConfigEnv): UserConfigExport => {
return {
plugins: [
viteMockServe({
mockPath: 'mock',
// 根据项目配置。可以配置在.env文件
enable: true,
}),
],
}
}
3、注意事项
-
无法在 mock.ts 文件中使用 node 模块,否则生产环境将失败
-
模拟数据如果用于生产环境,仅适用于某些测试环境。 不要在正式环境中打开它,以避免不必要的错误。 同时,在生产环境中,它可能会影响正常的 Ajax 请求,例如文件上传/下载失败等。