前言
马上就要做一次关于Easy Mock的培训,在这里对它做一个总结记录吧。
PS:建议直接看如何在项目中使用。
Easy Mock 简介
伪造数据,我们更高效
但,不仅于此
Easy Mock 是一个可视化,并且能快速生成 模拟数据 的持久化服务。
在下图中,我们可以看到 Easy Mock 首页给出的介绍(这里插一嘴,人家首页做的是真漂亮!):
那对于我们来说,什么时候使用呢?
前后端分离项目,工作进度又快,后端出接口的速度很大程度上会影响到我们前端的开发进度。这时候只要接口已经定义好了,我们就可以使用 Easy-mock 模拟接口返回数据来辅助我们进行功能的开发。等后端接口实现完成后,再进行联调。
Easy Mock 项目及接口创建
PS:这块可以不看,建议直接上 Easy Mock 自己动手尝试。
新建项目
- 进入个人项目这里,然后新建一个自己的测试项目
新建接口
- 点击刚才新建的项目进入接口列表页面
- 点击创建接口,选择接口Method,填写URL和描述,左侧内容就是该接口返回的内容,见下面示例
// 这是一个登录的post请求示例,登录成功失败随机
{
"data": function() {
return this.meta.code === 1 ? {
token: (new Date().getTime())
} : null
},
"meta": {
'code|1': [0, 0, 1],
message: function() {
return this.code === 1 ? '登录成功' : '用户名或密码错误,请重新输入'
}
}
}
Easy Mock 响应式数据
看到上边的示例,你可能会有疑问,你这个是随机的结果,如果我想根据用户输入的来控制返回数据呢?别急,Easy Mock 已经替我们想过了!
我们来看首页关于响应式的介绍
响应式数据
要数据联动那是不可能了,不过 Easy Mock 支持响应式数据。通过判断入参返回对应的数据。
阅读这段话,来划重点了!
通过判断入参返回对应的数据,是的,跟你想的一样一样的,就是通过入参来判断。
那我们接下来看看文档是怎么描述的。
我们可以在 数据编辑器 中,为某个属性指定一个 Function。在 Function 中,我们提供了 _req 对象,这使得我们可以通过请求对象编写逻辑,实现响应式数据,如图所示。
{
success: true,
data: {
default: "hah",
_req: function({
_req
}) {
return _req
},
name: function({
_req,
Mock
}) {
if(_req.query.name === 'nk'){
return _req.query.name + '_' + Mock.mock('@name')
} else {
return this.default
}
}
}
}
也就是说,我们可以通过使用 Function ,对 Function 参数进行处理来获得我们想要的数据。
这里我列几个我们最常用的,满足一下讲解需要,具体内容还是要 看详细文档 的。
MockMock 对象_req.params获取 url 参数对象_req.query将查询参数字符串进行解析并以对象的形式返回,如果没有查询参数字字符串则返回一个空对象_req.body当 post 请求以x-www-form-urlencoded方式提交时,我们可以拿到请求的参数对象
看到这里我们来将上面的登录接口修改成只有用户名是admin,密码是123才能登录,其他一律返回错误数据
{
"data": function({
_req,
Mock
}) {
const {
username,
password
} = _req.body
if (username === 'admin' && password === '123') {
return {
token: (new Date().getTime())
}
}
return null
},
"meta": {
code: function({
_req,
Mock
}) {
const {
username,
password
} = _req.body
if (username === 'admin' && password === '123') {
return 1
}
return 0
},
message: function() {
return this.code === 1 ? '登录成功' : '用户名或密码错误,请重新输入'
}
}
}
来更新一下我们的接口,然后点击预览接口。
可以看到,这个登录已经实现了我们上文提到的效果
更多的玩法可自行研究
Easy Mock 的 Mock.js
Easy Mock 内置了 Mock.js,我们可以更愉快的伪造数据了。
PS:下边是举的几个例子,具体还是得看 mock.js 官网,样例最多最全,还可以打开发者工具进行调试,这里就不做更多的说明了。
常用语法如下:
"string|1-10": "★", // 生成1-10个★
"integer": "@integer(10, 30)", // 生成10-30之间的数值
"date": "@date(yyyy-MM-dd)", // 随机日期 - date: "2015-09-04"
"datetime": "@datetime", // 随机时间 - datetime: "1971-01-05 18:55:33"
"url": "@url",
"email": "@email",
"city": "@city",
"county": "@county",
"image": "@image(200x200)",
"title": "@title",
Easy Mock 在项目中如何使用
重点来了,这个模块是本文的重点,因为本文是个人手打,纯个人理解,如果哪里我说的不对,或者解释模糊存在疑问的地方,还请您一定要指出来,共同学习进步。
- vue-cli 项目 这个简单,适用学习者,代码直接搬运即可。
- vue + egg.js 项目 这个是公司项目组成,不一定适用每个人,但我希望对你有所帮助。
vue-cli 项目
- 先将我们刚才新建项目的 Base Url 复制过来,这个相当于我们请求的服务器。
- 下方是我们每个接口的请求路径,见 api.js 文件。
- 新增
vue.config.js文件。
const path = require('path');
module.exports = {
devServer: {
// 自动打开页面
open: true,
proxy: {
'/mock': {
target: 'https://mock.mengxuegu.com/mock/60e656f3fd08e7028e4b926a',
// 是否允许代理(开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题)
changeOrigin: true,
// 地址重启(对请求路径进行重定向以匹配到正确的请求地址)
pathRewrite: {
'^/mock': '/mock' // 实际请求路径 http://localhost:8080/mock/user/login
// "^/mock": "/", // 实际请求路径 http://localhost:8080/user/login
}
}
}
},
configureWebpack: {
resolve: {
// 路径别名
alias: {
'@': path.join(__dirname, './src')
}
}
}
};
- 接下来,写一下我们的 api.js 文件(请求接口)。
// 这个文件是我的axios封装文件,想必大家都懂,这里就不放了。
import request from '@/utils/request.js'
// 登录验证
export function getUserList(data) {
// 将 Easy Mock 对应接口URL复制过来
return request({
url: '/mock/user/login',
method: 'post',
data
})
}
- 在项目中使用
import { getUserList } from '@/api.js';
// 调用接口
async getUserList() {
this.loading = true;
const params = {
username: 'admin',
password: '123'
}
const res = await getUserList(params);
const { meta, data } = res;
if (meta && meta.code === 1) {
// TODO 成功处理
} else {
// TODO 失败处理
}
this.loading = false;
}
vue + egg.js 项目
PS:再次声明,每个公司的项目配置不一定相同,但一定有借鉴的地方。接下来介绍仅针对本公司项目配置。
项目中使用了两种请求方式,两种请求各有千秋。
// 封装好的 axios 请求
import HttpRequest from '../utils/request';
export default class BaseApi {
static request(options) {
return HttpRequest(options);
}
static proxy(proxyName, options) {
// 注意这个/proxy,会在路由中拦截进行特殊处理
options.url = `/proxy/${proxyName}${options.url}`;
return HttpRequest({
...options,
...{
proxy: proxyName
}
});
}
static get proxyName() {
return process.env.proxyName;
}
}
- proxy 代理请求
优点:不需要再配置router和controller,减少代码量
- request 请求
优点:需要配置router和controller,功能方面更加灵活。
proxy 代理请求
我们先来看一下proxy方法如何在接口中使用的
import BaseApi from '@framework/api/base';
export default class ManageApi extends BaseApi {
static getRankData() {
// 这里的 this.proxyName 就是 process.env.proxyName
return this.proxy(this.proxyName.testMock, {
url: '/mock/xxx',
method: 'post',
});
}
}
注意:代码中的 this.proxyName.testMock,其中this.proxyName 就是上文中的 process.env.proxyName
接下来我们看一下路由是怎么拦截的
router.all(`${BASE_PATH}/proxy/*`, controller.proxy.index);
路由匹配所有以/proxy开头的请求地址,然后通过 controller.proxy.index 解析用户的输入,处理后返回相应的结果。
走到这里,我们需要了解以下两点
process.env.proxyName是如何配置的(这个相信大家都知道)?- controller下的proxy文件中的index方法做了什么处理?
- 我们先来看一下
process.env.proxyName的配置
在 build 文件夹的 env.dev.js 文件中添加 mock 服务代理(不允许添加到 Apollo/测试/生产环境)
const Extend = require('extend');
const DefaultENV = require('./env.default');
module.exports = Extend(true, DefaultENV, {
// 这个就是接口配置的mock代理字段
proxyName: {
testMock: 'test_mock'
}
});
build是 webpack 的配置文件
这里又延伸出一点
即 proxyName 配置的字段是如何代理mock服务的,先记下,下文做了解释。
- 接下来我们再看看controller下的proxy文件中的index方法做了什么处理。
// 简略代码
async index() {
const { ctx, service } = this;
const result = await service.proxyapi.index();
// 取出响应头
const resContentType = result.headers['content-type'];
// 根据响应头判断返回值是json格式,否则为字节流
if (resContentType.indexOf('application/json') > -1) {
// ... 下方省略如何处理的
} else {
// 处理下载文件
ctx.set('Content-Disposition', result.res.headers['content-disposition']);
ctx.set('Content-Type', resContentType);
ctx.body = result.data;
ctx.status = result.status;
}
}
这里的代码重点是这一行const result = await service.proxyapi.index();。
所以,重点是service.proxyapi.index是如何代理服务的。
提起精神来,马上就结束了要~~~
来,我们看一下service下proxyapi文件中的index方法是如何处理的。
// 简略代码
async index(params = {}) {
const { ctx } = this;
// 假设我们的 path: /proxy/testMock/user/login
// match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。
const urlRegResult = ctx.request.path.match(/\/proxy(.*)/);
const [
,
regUrl
] = urlRegResult;
// regUrl: /testMock/user/login
// exec() 方法用于检索字符串中的正则表达式的匹配。
const pathNode = PathToRegexp('/:apiName/:proxyURL*').exec(regUrl);
const [
,
apiName, proxyURL
] = pathNode;
// 看这两行!!!
const api = ctx.app.config.api || {};
const apiBaseURL = api[apiName];
if (!apiBaseURL) {
// TODO 路径不存在的处理
}
// 这里的url 就是我们实际的请求地址
const url = `${apiBaseURL}/${proxyURL}`;
const result = await this.proxyRequest(url, params);
return result;
}
重点来了!!!
看这两行代码!!!
const api = ctx.app.config.api || {};
const apiBaseURL = api[apiName];
上文我们留下了一个疑问,即 proxyName 配置的字段是如何代理mock服务的
在这里我们得到了解释,我们从ctx.app.config.api中将proxyName对应的请求地址取出来,组成最终的请求地址,即${apiBaseURL}/${proxyURL}。
好的,这个问题我们已经得到了解释。
接下来,我们只需要在ctx.app.config.api配置我们的请求地址即可。
config是 node server 的配置文件
// 简略代码
module.exports = (app) => {
const config = {};
config.api = {
// 这里我们配置了test_mock 对应的请求地址
test_mock:
// 这里需要写你需要的mock地址
'http://testmock.mock.com/mock/1e232f0bd0c4a41f5447df52',
};
};
OK,到此我们使用 proxy 方法的介绍已经完毕。
request 请求
- 方法2,使用的request方法(发送的请求会被node端拦截,所以我们需要配置好router以及controller),更简单些
首先我们还是看一下api方法是如何写的。
// 简略代码
static getAllMyData(data) {
return this.request({
method: 'post',
url: `/mock/getAllMyData`,
data
});
}
}
request方法需要配置路由
router.post(`/mock/getAllMyData`, controller.testData.getAllMyData);
然后在controller下的TestData文件中配置getAllMyData方法
// 简略代码
async getAllMyData() {
const { ctx } = this;
// 看这个请求路径 ctx.app.config.api.testMock
const url = `${ctx.app.config.api.testMock}/mock/getAllMyData`;
await this.proxyRequest(url);
}
在这里我们可以发现,我们的请求路径是ctx.app.config.api.testMock,有没有很熟悉的感觉,
没错,就是刚才我们配置的config文件。
好了,到此request的请求方式也介绍完了。
有需要的小伙伴,下来可以自己动手操作一遍了。
mock地址改为测试站地址
假设,现在后端已经开发完毕,前后端需要联调了,我们需要做的事情如下:
- proxy 代理请求:需要在
build文件中添加测试地址对应名称,然后将api文件中this.proxyName.xxx修改为测试地址对应名称即可。 - request 请求: 将controller中的
config.api.xxx修改为测试地址对应名称。
注意:如果config文件中没有配置测试地址对应名称,项目会自动去apollo.json文件中找。
补充
还有一些其他可以mock数据的方式,列举几个:
jsonS-server在本地起一个虚拟服务器,将数据存储到本身json文件中Mock.js在项目中会对接口请求进行拦截,返回本地 mock 数据YApi强烈推荐使用,高效、易用、功能强大的API管理平台,具有接口分组的优势。点我直达rap2类似Easy Mock,也是一个线上平台。点我直达
参考
- # 公司内部技术建设文档
- # Mock.js官网
- # Easy Mock
- # 浅谈 Easy-mock 最好的备胎没有之一
- # 利用Easy Mock简单模拟开发数据接口
- # 用 Easy Mock 模拟伪造服务器数据进行开发调试
- # vue 原生js 使用Easy Mock构建模拟数据
最后
- 文章是自己手敲,是对工作日常的总结,如有错误之处,敬请指正
- 如果遇到什么问题就留言吧,能解决大家帮忙一起解决一下