Mockjs
介绍
Mock官网首页是这么定义的:生成随机数据,拦截 Ajax 请求。
demo
项目mock例子:https://gitee.com/huangchunhongzZ/vue-mock-test
1、在项目中应用
引入js依赖
npm install mockjs
建一个mock文件夹来统一管理我们的mock数据
在mock文件夹下建一个demo.js尝试一下
在mock/demo.js中写下如下代码:
import Mock from 'mockjs'
//随机生成一个20-40条的数组数据试试
const projectList = Mock.mock({
"list|20": [{
'name': '@cname', // 中文名
'account': `@word`, // 英文单词
'phone': /1[3-9][0-9]{9}/, // 正则模式
'deptName': Mock.mock('@cword(2,4)'), // 随机2-4字中文单词
'id': '@guid', // guid
}]
})
//有多种模式可选,具体见官方示例。
export default [
{
url: '/Api/Project/GetList',
type: 'post',
response: (res) => {
// res.body就是我们传入到接口的数据,可以在这里做些逻辑操作
// res包含完整的请求头信息
return {
code: 200,
message: "操作成功",
data:projectList
}
// 使用return返回前端需要的数据
}
}
//... 多个接口
]
现在数据有了,我们如何让mockjs能够拦截到我们前端发出的请求,并能准确区分对应接口呢?
在mock/文件夹下再建一个index.js写我们mock的监听逻辑
import Mock from ‘mockjs’ // 导入mockjs
import demoApi from './demo' // 导入我们模拟数据的js文件
const mocks = [
{
intercept: true, // 开关,模拟请求与真实请求并存
fetchs: demoApi
},
// 解析地址栏参数解析函数
export function param2Obj(url) {
const search = url.split('?')[1]
if (!search) {
return {}
}
return JSON.parse(
'{"' +
decodeURIComponent(search)
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"')
.replace(/\+/g, ' ') +
'"}'
)
}
// 前端模式构建函数(或者你也可以建一个mock server)
export function mockXHR() {
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
Mock.XHR.prototype.send = function() {
if (this.custom.xhr) {
this.custom.xhr.withCredentials = this.withCredentials || false
if (this.responseType) {
this.custom.xhr.responseType = this.responseType
}
}
this.proxy_send(...arguments)
}
function XHR2ExpressReqWrap(respond) {
return function(options) {
let result = null
if (respond instanceof Function) {
const { body, type, url } = options
// https://expressjs.com/en/4x/api.html#req
result = respond({
method: type,
body: JSON.parse(body),
query: param2Obj(url)
})
} else {
result = respond
}
return Mock.mock(result)
}
}
for (const i of mocks) {
if(i.intercept){
for(const fetch of i.fetchs){
Mock.mock(new RegExp(fetch.url), fetch.type || 'get', XHR2ExpressReqWrap(fetch.response))
}
}
}
}
经过上面一通代码之后,我们已经初步完成了前端模拟数据的技术条件。
但是你千万不要忘记了,在main.js引入并使用它哦
// mock
if (process.env.NODE_ENV === 'development') {
const { mockXHR } = require('../mock')
mockXHR()
}
// mock end
src下建一个api文件夹
然后再在src/api/下建一个_request.js
import Axios from "axios";
// 定义axios配置
const http = Axios.create({
baseURL: '', // api的base_url
withCredentials: true, // 开启跨域身份凭证
method: "post",
headers: {
"Content-Type": "application/json;charset=UTF-8"
},
timeout: 5000 // request timeout
});
// 设置全局的请求次数,请求的间隙,用于自动再次请求
http.defaults.retry = 2;
http.defaults.retryDelay = 1000;
// 请求拦截器
http.interceptors.request.use(
function (config) {
return config;
},
function (error) {
return Promise.reject(error);
}
);
// 响应拦截器
http.interceptors.response.use(
function (res) {
return res;
},
function (err) {
let config = err.config;
let errres = err.response;
let err_type = errres ? errres.status : 0;
// 收集错误信息
switch (err_type) {
case 400:
err.message = "请求无效";
break;
case 401:
err.message = "由于长时间未操作,登录已超时,请重新登录";
break;
case 403:
err.message = "拒绝访问";
break;
case 404:
err.message = `请求地址出错: ${errres.config.url}`;
break;
case 405:
err.message = `未授权`;
break;
case 408:
err.message = "请求超时";
break;
case 500:
err.message = "服务器内部错误";
break;
case 501:
err.message = "服务未实现";
break;
case 502:
err.message = "网关错误";
break;
case 503:
err.message = "服务不可用";
break;
case 504:
err.message = "网关超时";
break;
case 505:
err.message = "HTTP版本不受支持";
break;
default:
err.message = "网络波动,请重试";
}
// If config does not exist or the retry option is not set, reject
if (!config || !config.retry) return Promise.reject(err);
// Set the variable for keeping track of the retry count
config.__retryCount = config.__retryCount || 0;
// Check if we've maxed out the total number of retries
if (config.__retryCount >= config.retry) {
// Reject with the error
return Promise.reject(err);
}
// Increase the retry count
config.__retryCount += 1;
// Create new promise to handle exponential backoff
let backoff = new Promise(function (resolve) {
setTimeout(function () {
resolve();
}, config.retryDelay || 1);
});
// Return the promise in which recalls axios to retry the request
return backoff.then(function () {
return http(config);
});
}
);
export default http;
封装了一下axios之后,所有的api接口仍建议统一管理
我们在api/文件夹下再建一个project.js用来统一管理项目模块的所有接口
import request from "../_request";
// 获取部门列表接口
function getProjectListApi(data) {
return request({
url: "/Api/Project/GetList",
method: 'post',
data
});
}
export {
getProjectListApi // 获取部门列表接口
}
接下来就是最后一步,在我们开发的.vue文件中使用啦
import { getProjectListApi } from "@/api/project.js"; // 导入用户列表接口
export default {
data(){
return {
projectList: []
}
},
created(){
this.getProjectList()
},
methods: {
getProjectList(){
getProjectListApi().then(res => {
console.log(res)
})
}
}
}