参考链接:https://blog.csdn.net/qi8023for/article/details/127618742
1、安装MSW npm install msw2、工程下创建一个 mocks 文件夹和handlers.js 和 browser.js文件
handlers.js 定义MOCK API行为:import { rest } from 'msw'
export default [ rest.get('/message', (req, res, ctx) => { return res( ctx.json({ message: 'it works :)' }) ) })
browser.js 中初始化 mock service worker:
import { setupWorker } from 'msw'import handlers from './handlers'
export const worker = setupWorker(...handlers)
在 main.js 中导入并初始化 MSW:
import { createApp } from 'vue'import App from './App.vue'
// 仅在开发环境中启动 MSWif (process.env.NODE_ENV === 'development') { const { worker } = require('./mocks/browser') worker.start()}
createApp(App).mount('#app')
3、在 public 文件夹中生成 service worker 脚本:npx msw init public/
4、运行并测试应用npm run serve
===========第二种方法:
使用mockjs插件安装插件 npm install mockjs --save-dev在 src 目录下创建一个 mocks 文件夹,并在其中创建 index.js 和 data 文件夹,用于存放模拟数据。在 mocks/index.js 中配置 mock 数据:const Mock = require('mockjs');// 格式: Mock.mock( url, 'post'|'get' , 返回的数据)Mock.mock('/api/test', 'get', require('./data/test.json'));Mock.mock('/api/test2', 'post', require('./data/test2.json'));
在 main.js 中引入 mock 数据:require('./mock');
在 Vue 组件中使用: axios.get('/api/test') .then(res => { console.log(res); }) .catch(err => { console.log(err); });
===========第三种方法:
public 文件夹中放置 mock 数据不需要使用mockjs插件 将 JSON 数据文件放在 public/mock 文件夹中。 配置 vue.config.js
module.exports = { devServer: { proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true, pathRewrite: { '^/api': '/mock' } } } } }; 在VUE组件中使用: axios.get('/api/test.json') .then(res => { console.log(res); }) .catch(err => { console.log(err); });
============第四种方法:创建 Node.js 服务:在项目根目录创建一个 serve.js 文件,编写 Node.js 服务器代码。启动服务: node serve.js配置 vue.config.js 的 proxy: module.exports = { devServer: { proxy: { '/api': { target: 'http://localhost:9000', changeOrigin: true, pathRewrite: { '^/api': '' } } } } };
在 Vue 组件中使用:
axios.get('/api/test')
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
// Mock.mock('/api/add', 'post', (options) => { // const body = JSON.parse(options.body); // body.id = dataList.data.length + 1; // 简单模拟ID自增 // dataList.data.push(body); // return { // code: 200, // message: '添加成功' // }; // }); // // 更新数据
//注意此处用正则表达式匹配接口重要url字段,d+表示匹配数据,也可也匹配字符串等。
带参数的也可以不在url中拼接,用正则匹配前段url,不匹配后面参数
// 比如url /tag-api/pactera-cg/cg/customs/list?pageNum=1&pageSize=10&cgS // Mock.mock(/\/api\/update\/\d+/, 'put', (options) => { // const id = parseInt(options.url.split('/').pop()); // const body = JSON.parse(options.body); // let updated = false; // dataList.data.forEach(item => { // if (item.id === id) { // Object.assign(item, body); // updated = true; // } // }); // return { // code: updated ? 200 : 404, // message: updated ? '更新成功' : '数据未找到' // }; // }); // // 删除数据 // Mock.mock(/\/api\/delete\/\d+/, 'delete', (options) => { // const id = parseInt(options.url.split('/').pop()); // let deleted = false; // dataList.data = dataList.data.filter(item => { // if (item.id === id) { // deleted = true; // return false; // } // return true; // }); // return { // code: deleted ? 200 : 404, // message: deleted ? '删除成功' : '数据未找到' // }; // });
一、Mock简介Mock.js官网提供的Mock示例及Wiki文档,对Mock的使用描述的非常详细,并且可以在控制台快速试验这些方法。
二、Vue 项目中使用 mock.js 拦截数据注:使用vue init project-name 创建的Vue项目
1、安装相关依赖npm install axios –savenpm install mockjs --save-dev122、模拟Mock数据通过配置devServer.before选项,设置url访问路径及response响应数据,进行mock数据。使用Mock.mock(),根据数据模板生成模拟数据。2.1 Mock数据模拟方式一:devServer.before在src文件夹下新建mock文件夹及index.js,在index.js中统一处理所有的mock数据
在index.js文件中引入mock、声明随机数据、暴露拦截方法
const Mock = require('mockjs') // 引入mockjs
module.exports = function (app) { // 暴露一个函数,用于拦截请求时触发 //监听http请求: app是一个请求实例,.get方法第一个参数传需要拦截的url,第二个参数传一个函数,该函数有两个参数(也可用app.post) app.get('/user/userInfo', (rep, res) => { // 设置要返回的数据(用mock随机生成的数据) let json = { id: '@id()', // 得到随机的id username: '@cname()', // 随机生成中文名字 email: '@email()', // email ip: '@ip()', // ip地址 description: '@paragraph()', // 描述 date: '@date()' // 随机生成日期 } // 通过res.json将上面声明的随机数据转为json并作为请求的返回值返回 res.json(Mock.mock(json)) })}
12345678910111213141516171819配置config进行拦截在config.js(build->webpack.dev.conf.js或vue.config.js)中配置拦截,使用devServe.before钩子函数,用来监听来自web的http请求(在所有请求前先执行该函数)。引入刚刚编辑好的mock->index.js,该js文件暴露的函数将在这里调用。(我这里是在build->webpack.dev.conf.js中配置的)
module.exports = { devServer: { before: require('./mock/index.js') // 引入 mock/index.js }}123452.2 Mock数据模拟方法二:Mock.js在src文件夹下新建mock文件夹及index.js,在index.js中统一处理所有的mock数据在index.js文件中引入mock、声明随机数据、暴露拦截方法import Mock from 'mockjs'
//表示需要拦截的 URL,可以是 URL 字符串或 URL 正则。//表示需要拦截的 Ajax 请求类型。例如 GET、POST、PUT、DELETE 等。//表示数据模板,可以是对象或字符串。例如 { 'data|1-10':[{}] }、'@EMAIL'。Mock.mock('/user/userInfo', 'get', { id: '@id()', // 得到随机的id username: '@cname()', // 随机生成中文名字 email: '@email()', // email ip: '@ip()', // ip地址 description: '@paragraph()', // 描述 date: '@date()' // 随机生成日期})12345678910111213在main.js中引入require("./mock/index.js")3、在vue使用发送http请求的URL与mock中定义的URL需一致
import axios from "axios";export default { mounted() { axios.get('/user/userInfo').then(res => { console.log(res); }).catch(err => { console.log(err); }) }}123456789104、效果
PS:如果发送http请求的URL与mock中定义的URL不匹配或不存在的话,就会报404错误! 请确认URL没问题。
三、Mock使用优化1、mock数据使用单独的js文件1.1 场景描述所有接口的mock数据都在index.js里处理,在接口太多的情况下查找及修改很不方便,因此将模拟的mock数据单独放入对应的js文件(可按接口或业务需求进行处理)。
1.2 解决方案在mock文件夹下新建userInfo.js,在userInfo.js写入该接口模拟的mock数据。/** * 写法一 */// module.exports = {// id: '@id()', // 得到随机的id// username: '@cname()', // 随机生成中文名字// email: '@email()', // email// ip: '@ip()', // ip地址// description: '@cparagraph()', // 描述// date: '@date()' // 随机生成日期// }
/** * 写法二 */// const json = {// id: '@id()', // 得到随机的id// username: '@cname()', // 随机生成中文名字// email: '@email()', // email// ip: '@ip()', // ip地址// description: '@cparagraph()', // 描述// date: '@date()' // 随机生成日期// }// module.exports = json
/** * 写法三 */const userInfo = () => { const json = { id: '@id()', // 得到随机的id username: '@cname()', // 随机生成中文名字 email: '@email()', // email ip: '@ip()', // ip地址 description: '@cparagraph()', // 描述 date: '@date()' // 随机生成日期 } return { data: { result: json, code: 200, message: 'success' } }}module.exports = { getUserInfo: userInfo}123456789101112131415161718192021222324252627282930313233343536373839404142修改mock->index.js文件,使用require('./userInfo.js')来获取模拟的json数据const Mock = require('mockjs') // 引入mockjs
module.exports = function (app) { // 暴露一个函数,用于拦截请求时触发 //监听http请求: app是一个请求实例,.get方法第一个参数传需要拦截的url,第二个参数传一个函数,该函数有两个参数(也可用app.post) app.get('/user/userInfo', (rep, res) => { // 设置要返回的数据(用mock随机生成的数据) // let json = { // id: '@id()', // 得到随机的id // username: '@cname()', // 随机生成中文名字 // email: '@email()', // email // ip: '@ip()', // ip地址 // description: '@cparagraph()', // 描述 // date: '@date()' // 随机生成日期 // } // const json = require('./userInfo.js') // userInfo.js直接返回json数据(对应写法一、二) const json = require('./userInfo.js').getUserInfo() // userInfo.js返回函数(对应写法三) // 通过res.json将上面声明的随机数据转为json并作为请求的返回值返回 res.json(Mock.mock(json)) })}12345678910111213141516171819202、mock获取get、post请求参数2.1 场景描述在前后端分离的开发模式下,想要尽可能的模拟真实情况,如不同的请求方式get/post,接口超时响应等。
2.2 解决方案2.2.1 设置延时请求到数据1.不设置延时很有可能遇到坑【敲黑板】,因为真实的请求是需要时间的,mock不设置延时是拿到数据马上返回。2.要模拟Loading加载效果时。
//设置延迟响应,模拟向后端请求数据Mock.setup({ timeout: 800})12342.2.2 get请求参数Mock.mock("/api/order/index", "get", (options) =>{ let result = {} // 数据或对象 return { data: { result: result, code: 200, message: 'success' } }});1234注意:get 请求如果带参数的话,是在URL后面加上参数,因此和设置的URL没有匹配上,会导致URL没找到请求失败。举个例子:使用 Mock.mock(“/user/getUserInfo”, “get”, mockData) 时,它只会拦截URL等于/user/getUserInfo的请求,而对于带参数的请求,如/user/getUserInfo?id=123就拦截不到。
建议将URL改写成正则表达式的URLMock.mock(RegExp(url + ".*"), "get", mockData);
Mock.mock(RegExp("/api/order/index"+ ".*");, "get", (options) =>{ let result = {} // 数据或对象 return { data: { result: result, code: 200, message: 'success' } }});12342.2.3 post请求参数post请求可以是 URL 字符串或 URL 正则。
Mock.mock("/api/order/index", "post", (options) =>{ let result = {} // 数据或对象 return { data: { result: result, code: 200, message: 'success' } }});12343、mock返回列表及分页数据3.1 场景描述在mock文件夹下新建order.js,以订单列表为例,我们模拟了订单列表数据,但列表数据还需分页才能满足业务需求。
3.2 解决方案在现有的列表数据基础上进行改造,增加分页功能。
未分页的orderLIstconst orderList = () => { const dataList = [] for (let i = 0; i < 100; i++) { const newObject = { orderId: '@id()', // 得到随机的id orderType: '@cword("全次极加延", 1)', // 得到随机的文本 createTime: '@datetime()' // 随机生成日期 } dataList.push(newObject) } return { data: { result: dataList, code: 200, message: 'success' }}}module.exports = { getOrderList: orderList}123456789101112131415分页的orderLIstconst orderList = (params) => { const dataList = [] for (let i = 0; i < 100; i++) { const newObject = { orderId: '@id()', // 得到随机的id orderType: '@cword("全次极加延", 1)', // 得到随机的文本 createTime: '@datetime()' // 随机生成日期 } dataList.push(newObject) } const { page, pageSize } = params const total = dataList.length const len = total / pageSize const totalPage = Number.isInteger(len) ? len + 1 : len const list = dataList.slice((page - 1) * pageSize, page * pageSize) return { data: { result: { page, pageSize, total, totalPage, list }, code: 200, message: 'success' } }}module.exports = { getOrderList: orderList}1234567891011121314151617181920212223242526272829304、控制mock在开发环境使用,在生产环境禁用4.1 场景描述mock拦截所有的axios请求,根据请求做出相应的响应。在前后端分离开发时我们使用mock获得相应的数据,但当和后端联调时不禁用mock的话,就无法获得后端接口数据,因此我们来配置一个mock模拟数据的开关。
4.2 解决方案在vue中通过设置main.js中的Vue.config.productionTip来决定模式。默认为false是生产环境。我们在config/dev.env.js和config/prod.env.js中设置变量。// dev.env.js下的配置。module.exports = merge(prodEnv, { NODE_ENV: '"development"', MOCK: true //开发环境使用mock})
// prod.env.js下的配置module.exports = { NODE_ENV: '"production"', MOCK: false // 生产环境禁用mock}
123456789101112在main.js中设置process.env.MOCK && require("./mock/index.js")。process.env.MOCK这句就是判断刚才设置的值,如果是true,才会执行语句引入mock,如果是false,则后面的语句不执行,即不引入mock。
总结Mock原理:前端发送请求后,在devServe.before中运行mock/index.js暴露的函数,捕捉到url一致的请求,直接返回mock设定的数据,有返回值就不会继续真实的请求,拦截成功之后,请求没有往后台去,而是在前端完成了虚拟请求。————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 原文链接:https://blog.csdn.net/qi8023for/article/details/127618742