Mock
mock 介绍
目的
方便生成随机数据,拦截Ajax请求。
偶尔会写一些前端的项目,参考一些比较知名的UI框架,里面很多例子都会把数据直接写在里面,作为参考,因此很多项目里面也会这样手写数据,直接写死在前端,将代码与mock数据紧密结合在一起,每次需要修改数据,都需要直接改动到代码层,前端本身改动就非常大,如此频繁的修改代码层面显然不是很好的实践。
同时手写的数据,美观与真实性差异就看作者水平了。
优点
- 非常简单强大,入手快
- 拦截api请求,mock出真实的前后端交互情况
- 更改mock数据方便,与业务代码分离,频繁修改也不会有太大的危险
- 在后端接口准备好前,通过mock接口来模拟与后台的交互,同时调整数据结构。
- 开发过程中,mock数据也可以与后端提前讨论,引导后台的数据结构更加合理。
- 后台开发完以后,可以一次性切换接口
缺点
- 灵活性不够,无法mock后台一些异常处理返回
- Build成静态文件以后线上无法使用(或许我没有找对方法)
comment
针对第一个问题,忽然想到一种方案,或许你可以在同一个接口里面,mock不同的response,然后采用随机函数,随机的返回各种异常response,这样可以测试前端应对各种后台error作出的处理是否符合预期。
安装
cd myProject
#仅安装到本地开发环境
npm install mockjs --save-dev
mock 实现
src
│
└───api //api文件夹,所有的接口都到单独抽出来,放在该目录下
│ index.js //入口函数,对外暴露
│ search.js //为每一类接口单独创建的文件,一类接口统一放在一个目录下
│
└───mock
index.js //所有的mock api都会写在下面,如果需要,也可以拆分
mock/index.js
/**
* data mock refer to http://mockjs.com
*
*/
const Mock = require('mockjs');
const util = require('./util');
module.exports = function (app) {
app.get('/mock/v1/search', function (rep, res) {
let result = {
"data|24": [{
"date": "@date('yyyy-MM-dd')",
"logNum": "@natural(60, 1000)"
}
]
};
//util.wrapResultSuccess 包装了response返回,规范统一
res.send(util.wrapResultSuccess(Mock.mock(result).data));
});
}
vue.config.js
//vue cli3 配置文件
devServer: {
port: port,
open: true,
host: '127.0.0.1',
https: false,
hotOnly: false,
overlay: {
warnings: false,
errors: true
},
#根据当前环境,把整个mock目录加载到项目中,每次修改mock文件需要重启
before: process.env.ENV == 'mock' ? require('./src/mock'):null,
},
api/index.js
/**
* api interface
*/
import search from '@/api/search'
export default {
search
}
api/search.js
/**
* article模块接口列表
*/
import axios from '@/plugins/request';
import trend from "@/plugins/handle"
const search = {
statusPing () {
return axios.get(`/status_ping`);
},
//search
search (body) {
return axios.get(`v1/search`, body);
},
export default search;
utils/request.js
把axiso做了一层封装,每一次前端请求都会把x-request-id带给后台,后台打印日志的时候,都会打印这个id,方便日后追踪问题,同事针对一些后台的error,可以做一些统一的处理。
import router from '@/pages/login/router';
const xss = require("xss");
let instance = axios.create({
timeout: 1000 * 60
});
instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
function getRandomTraceId() {
let characters = 'abcdefghijklmnopqrstuvwxyz1234567890';
let result = '';
let idLength = 32;
try {
for (let index = 0; index < idLength; index++) {
result += characters[parseInt(Math.random() * characters.length, 10)];
}
} catch (error) {
result = 'getRandomTraceIdError';
}
return result;
}
/**
* request interceptor
* Before each request, if token exists, carry it in the request header
*/
instance.interceptors.request.use(
config => {
// console.log(JSON.stringify(config));
//add trace id for request
config.headers['x-request-id'] = getRandomTraceId();
//xss filter request url
config.url = xss(config.url);
// 登录流程控制中,根据本地是否存在token判断用户的登录情况
// 但是即使token存在,也有可能token是过期的,所以在每次的请求头中携带token
// 后台根据携带的token判断用户的登录情况,并返回给我们对应的状态码
// 而后我们可以在响应拦截器中,根据状态码进行一些统一的操作。
// const token = store.state.token;
// token && (config.headers.Authorization = token);
return config;
},
error => Promise.error(error))
instance.interceptors.response.use(
res => res.status === 200 ? Promise.resolve(res) : Promise.reject(res),
error => {
const {response} = error;
if (response) {
errorHandle(response.status, response.data.message);
return Promise.reject(response);
} else {
// 处理断网的情况
// eg:请求超时或断网时,更新state的network状态
// network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
// 关于断网组件中的刷新重新获取数据,会在断网组件中说明
if (!window.navigator.onLine) {
// store.commit('changeNetwork', false);
} else {
return Promise.reject(error);
}
}
});
export default instance;
—main.js
直接把api类挂载到vue上,这样方便使用,也可以直接到使用类里面去引入
import api from '@/api'
Vue.prototype.$api = api;
window.APP=new Vue({
router,
i18n,
api,
store,
render: h => h(App)
}).$mount('#app')
how to use
async getData(){
let response = await this.$api.search.search(request);
if (response.status == 200 && response.data.data) {
console.log(`response.data.data = &{response.data.data}`);
}
}
来源:CSDN
作者:小疯子_的博客
链接:https://blog.csdn.net/u011958281/article/details/103483446