前言
在现在的前后端分离的项目开发中,为了不影响项目的进度,都是前后端同时进行开发。为了不影响咱们前端开发的进度,通常都是由后端同学,先提供接口文档,然后前端同学对照这接口文档来进行数据的模拟来完成前后端对接的工作。这里的数据模拟其实也就是大家平时所说的mock数据,那么前端当中有哪些方式来实现mock数据呢???…(⊙_⊙;)…咱们接着往下聊!(●^o^●)
前端的mock数据
在前端的mock数据的解决方案有很多种,这里咱就由浅入深的聊聊(装个B(((┏(; ̄▽ ̄)┛装完逼就跑)。 首先最简单的就是 我们在页面中写的死数据(原本应该从接口获取的,但是在页面中写死了); 其次就是使用mock.js进行mock数据;在咱们的项目中还有哪些mock方式,接下来咱就展开了好好聊聊
mock.js
在前端的项目中使用 mock.js ,相信大家也都使用过,这里就不再详细的描述了,在前端项目中使用 mock.js 包,然后本地手写mock数据模拟,在前端代码中产生一大堆的mock代码,引入不必要的js文件。
在线mock服务
fastmock 无数据校验,正常mock功能,有固定的前缀和后面自定义的uri ,没有对于传入参数的配置,只有返回值的配置,接口 mock 变得更加简单,让团队协作变得更加高效。
小结
- 前端项目中使用 mock.js 包,前端代码中产生一大堆的mock代码,引入不必要的js文件。
- 在线mock,前端安装接口文档,等到后端接口开发完成之后,再将前端的接口请求地址更改为后端的地址进行联调即可。
在笔者的上一家公司的时候,功能都快要提测了,遇见一个奇葩的问题,也因此一个乖巧的我,第一次在办公室和一个java后端干了起来,事情的起因是这样的。。。 项目原本是的php开发的,后来因为种种原因吧(你懂得),后端变成了,php+java的开发模式,这种模式,当时也是公司的技术团队的第一次使用,然后就出现了一个奇葩的问题,一个非常重要的接口,前端发送请求,传递出去了参数,但是后端收不到(请求地址,协议,字段都正确),然后就开始找问题,后端说:“不是我的问题,我打断点,确实是没有收到参数。你再检查一下,是不是前端这边有问题。”
于是我又检查了一遍,确实没有问题,查看浏览器的请求,参数也确实传递到的正确,然后就是相互扯皮了,经过了种种的测试,分析检测,最终解决了问题是后端的nginx的代理配置的问题。
手撸mock服务
经历过和后端的撕扯之后,一怒之下,自己在家用一个多小时的时间,直接就手撸了一个mock服务,然后就贡献给了公司,开始了公司内部进行使用,主要有以下几个方面,让我有一个自己搞mock服务的想法, 首先笔者脑子太笨了,记不住 mockjs那么多的api,主要还是自己用的少,不习惯(哈哈) 其次就是一些数据和公司的数据库中的数据有着上下游的联系,然后根据公司的业务,写了下面的这个本地的mock服务,主要还是能够检查参数是否正确,已经错误的情况下的处理。当然了,最重要的原因就是,下次后端再说接收不到参数的时候,直接回怼回去:“我node都可以接收到参数,你java不可以??你写的代码有问题,去检查一下吧😄”,接下来咱就看看这个用一个多小时写的mock服务是啥样的(*❦ω❦)
项目
技术栈肯定的是使用了我们大前端小伙伴最熟悉的Node写的,使用的是koa框架,项目效果如下:
授人以鱼不如授人以渔,所以咱先原理,后项目代码,哈哈哈!(^-^)V
项目原理:
其实对于这个整个项目的最核心也是最简单的一个原理其实就是大家之前刚学js的时候都学过的一个api Math.random()
: 返回介于 0(包含) ~ 1(不包含) 之间的一个随机数;然后我们再来基于这个api
来封装一个简单的函数
/**
* @description: //!生成从minNum到maxNum的随机数
* @param {number} minNum 小区间的数值范围 默认值1
* @param {number} maxNum 大区间的数值范围 默认值10
* @return {number} 生成的随机的数值
*/
const randomNum = (minNum = 1, maxNum = 10) => {
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
}
接下来就是我们的mock的api功能的开发,先来一个随机生产文章的标题的api,为了使用的方便,所以在函数中,都进行了范围的默认值的设置,
/**
* @description: //!随机生成标题
* @param {number} min 最小的字符串区间,默认值10
* @param {number} max 最大的字符串区间, 默认值30
* @return {string} tmp 在指定的返回内随机的生成标题的内容
*/
const randomTitle = (min = 10, max = 30) => {
if (min > max || min <= 0) {
return "输入的数据有误!";
}
let str = '最灵繁的人也看不见自己的背脊 有勇气承担命运这才是英雄好汉 越是无能的人,越喜欢挑剔别人的错儿 一切节省,归根到底都归结为时间的节省';
let tmp = '';
let sum = randomNum(min, max);
for (let i = 1; i <= sum; i++) {
tmp += str.charAt(Math.floor(Math.random() * str.length));
}
return tmp;
}
看到了这里,是不是觉得实现这个功能很简单,
接下来,我们再来写一个随机生产验证码内容:
/**
* @description://!随机生成字符串的工具函数
* @param {number} min 最小的字符串区间,默认值10
* @param {number} max 最大的字符串区间, 默认值30
* @return {string} tmp 返回在区间范围内的字符串
* @author: LuKang
*/
const randomString = (min = 10, max = 30) => {
if (min > max || min <= 0) {
return "输入的数据有误!";
}
let str = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';//@去除了易混淆的字符
let tmp = '';
let sum = randomNum(min, max);
for (let i = 1; i <= sum; i++) {
tmp += str.charAt(Math.floor(Math.random() * str.length));
}
return tmp;
}
通过上面的两个例子,是不是发现它们其实都是大同小异的,剩下的就是举一反三了,你可以写出以下的内容: 随机生产姓名,随机生成身份证,随机生成备注信息,随机生成手机号,随机生成日期时间。。。
注:上面的演示的代码还有优化的空间和扩展的空间哦
项目
项目是基于koa框架来完成的,在上文中的大家首先看到的这个截图是下图这样的效果:
首先的是这个项目的 立体的 文本展示效果,使用的是 alphabetjs 这个依赖包
const Alphabet = require('alphabetjs');
const SymbolLu = Alphabet('SymbolLu', 'stereo');//@planar 平面 ,stereo立体
console.log(SymbolLu)
控制台默认是白色的,接下来我们就使用colors 这个包来改变控制台打印的文本的颜色
const Alphabet = require('alphabetjs');
const SymbolLu = Alphabet('SymbolLu', 'stereo');//@planar 平面 ,stereo立体
console.log(SymbolLu.green)
然后就是这段的接口的BaseUrl的输出,其实它就是一个模板字符串
的拼接 http://${getIPAdress()}:${PORT}
const { PORT } = require('../../config.js');
//!获取ip地址
getIPAdress = () => {
let interfaces = require('os').networkInterfaces();
let ip = '';
for (let devName in interfaces) {
let iface = interfaces[devName];
for (let i = 0; i < iface.length; i++) {
let alias = iface[i];
if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
ip = alias.address
}
}
}
return ip;
}
到这里是不是发现还可以,也挺有趣,接下来就是,接口的控制器(controllers)路由(routers)的业务了 先配置一下路由
const demo = require("../controllers/demo")//!路由中导入控制器导出的函数
/**
* @type {Custom.IRouter}
*/
module.exports = router => {
router.prefix("/demo")// 设置路由的前缀
router.post("/", demo.index);// 设置的是post请求
router.get("/data", demo.index);// 这里面的接口的地址为 【控制台中的接口的BaseUrl】+【路由的前缀】+路由的信息
// 例如 http://192.168.199.15:3000/demo/data
router.post("/possible", demo.possibleError)
router.get("/pagingList", demo.paging)// 分页
}
然后我们再来看看这个控制器
module.exports = {
/**
* @description: 这个接口只是演示了如何怎么基础的使用这个项目进行数据的模拟
*/
async index(ctx, next) {
const { name, age } = ctx.request.query;//!这个是get请求获取到的参数(使用了解构赋值,将前端传递处理的参数结构出来)
console.log(name, "name")
console.log(age, "age")
//!这里使用random里面的函数进行模拟数据,具体函数的入参和返回值,请将鼠标悬浮在函数的名称上面会有提示
let tel = ctx.random.randomPhone();//@随机产生一个手机号
let str = ctx.random.randomString();//@随机产生字符串
let strName = ctx.random.randomName();//@随机产生一个姓名
ctx.success({ tel, name, age, str, strName })//@成功的返回,会将生成的数据在接口中返回给前端
}
}
你是不是会有疑问这里的ctx
里面是怎么获取到我们写的 randomPhone()
,首先这里是对koa
中的context对象
做了扩展,扩展的内容如下:
// extend/context.js
const context = {}
const config = require("../config")
const random = require("../tools/random")
const utils = require("../tools/utils")
context.config = config
context.random = random
context.utils = utils
/**
* 成功返回
* @param {any} data
* @param {number} status {默认为200}
*/
context.success = function (data, status = 200) {
const statusIsNumber = typeof status === "number"
if (!statusIsNumber) {
throw new Error("返回状态码status必须是number类型")
}
let msg = 'success';
let code = 1;
// 加入随机出错的代码开始
let number = context.random.randomNum();
if ( number == 8 ) { // 随便来一个随机出错的数字
// 出错的逻辑
msg = 'fail';
code = 0;
this.status = 500
data = [];
this.body = {code, msg, status:500, data}
} else {
this.status = status
this.body = {code, msg, status, data }
}
}
/**
* 失败返回
* @param {obj} data
* @param {number} status {默认为500}
*/
context.err = function (data, status = 500) {
const statusIsNumber = typeof status === "number"
if (!statusIsNumber) {
throw new Error("返回状态码status必须是number类型")
}
this.status = status
let msg = data.msg ? data.msg :'fail'
this.body = {code:0, msg, status, data }
}
module.exports = context
然后又在index.js中进行了导入
// idnex.js
const { resolve } = require("path")
const CustomKoa = require("./custom/app")
const context = require("./extend/context")
const middlewares = require("./middlewares")
const path = require('path')
const static = require('koa-static')// koa中的设置静态服务的中间件
const cors = require('koa2-cors');// 处理跨域
const colors = require('colors');// 引入colors库用于设置控制台中打印的颜色
const staticPath = './static'
const app = new CustomKoa()// 这个 CustomKoa 是一个在原本的koa中进行了继承之后添加了扩展的Koa的类
app.use(cors(context.config.Cors))// 设置跨域的处理
app.useMiddlewares(middlewares)// 注册中间件
// 设置控制台的主题
colors.setTheme(context.config.Theme);
app.useRouters(resolve(__dirname, "./routers"))
app.use(static(path.join(__dirname, staticPath)))// 设置静态服务的中间件
app.extendContext(context)
module.exports = { server: app }
这个mock服务的核心代码就是这些了(#^.^#),虽然在当时的 自己手撸的这个mock 服务,满足了当时我们前端团队的 使用,毕竟当时上家公司也是只有6个前端使用,在一定的程度上提高了我们的工作效率,有了更多的摸鱼(学习)的时间,但是它还是有很多的不足,毕竟这个当时也只是一个内部使用的项目,为了公司内部的使用而开发的项目地址完整代码点这里
注:由于之前的完整项目涉及到公司的内容,这里给搭建提供的是一个删减版的demo服务,大家感兴趣的话,可以自己丰富扩展哦!
mock数据的痛点
手撸完了mock服务,再就再深入了基于mock服务聊聊。mock数据虽然在一定的程度上,能够提高我们的开发效率,但是我们还是需要花费一定的时间去写mock数据,即便我们已经拥有了那么多的mock工具,像我们在上面聊的那么多的mock解决方案,但是它们也都还存在一个问题,这个问题就是,你需要看着接口文档去mock数据
此时你有没有觉得,笔者提出的这个问题很 扯淡嘛,本来就是要使用 mock数据来提高我们前后端对接的开发效率,看着接口文档去mock数据肯定是必不可少呢啊,不然咋mock和接口一样的数据数据呢??好了,当然了,人都是懒惰的,现在,我们又增加了一个痛点,就是需要按照接口文档去mock数据 ≡┏|*´・Д・|┛
那这个痛点,的解决方案,也是笔者感觉我们前端mock数据的最终的解决方案,不用自己手动的去mock,让工具能够基于我们的接口文档,自动的去mock,是不是更高效了,接着咱就来聊聊这个最终的痛点解决方案
痛点的解决方案
Apifox (opens new window)是 API 文档、API 调试、API Mock、API 自动化测试一体化协作平台,定位 Postman + Swagger + Mock + JMeter
。
基于上面的痛点,一直到笔者认识到了这个开发(测试)工具,才是真正的得到一个完美的解决,它就是Apifox,官方给了一个简单的公式,更能说明Apifox可以做什么。
Apifox = Postman + Swagger + Mock + JMeter
通过一套系统、一份数据,解决多个系统之间的数据同步问题。只要定义好 API 文档,API 调试、API 数据 Mock、API 自动化测试就可以直接使用,无需再次定义;API 文档和 API 开发调试使用同一个工具,API 调试完成后即可保证和 API 文档定义完全一致。高效、及时、准确!很强大的开发工具 哈哈哈,一句话 Apifox 牛逼
Apifox的特点:
- 接口文档定义:
Apifox 遵循 OpenApi 3.0 (原 Swagger)、JSON Schema 规范的同时,提供了非常好用的可视化文档管理功能,零学习成本,非常高效。 - 接口调试:
Postman 有的功能,比如环境变量、预执行脚本、后执行脚本、Cookie/Session 全局共享 等功能,Apifox 也都有,并且还是国人开发的最重要的中文界面。 - 数据 Mock:
内置 Mock.js 规则引擎,非常方便 mock 出各种数据,并且可以在定义数据结构的同时写好 mock 规则。支持添加“期望”,灵活配置根据参数值返回不同数据内容。最重要的是 Apifox 零配置 即可 Mock 出非常人性化的数据,也是咱这篇文章介绍的重点,后端写完接口文档,咱前端的Mock数据就有了。 - 接口自动化测试:
提供接口集合测试,可以通过选择接口(或接口用例)快速创建测试集。目前接口自动化测试更多功能还在开发中,目标是: JMeter 有的功能基本都会有,并且要更好用。 - 团队协作:
Apifox 天生就是为团队协作而生的,接口云端实时同步更新,成熟的团队/项目/成员权限管理,满足各类企业的需求
当然了,咱这里主要聊的是它的Mock数据的能力,
使用心得
起初我们团队(目前所在在团队)后端每次写完接口文档之后还需要给前端去造数据(mock数据),我们公司的前端比较硬气,让后端同学搞mock数据😄,后端同学也是需要花费一定的时间去写脚本,毕竟项目的开发时间很紧,于是我们便在想,如何能够省掉这个造数据的时间,所以我们就迁移了接口文档到Apifox 使用 它来进行接口文档的管理,后端只需要去设计接口文档,设置完类型之后,就可以使用它的mock服务。会自动的生成我们所需要的mock数据服务,再也不用手动的去写mock服务了最重要的是 ,基于公网的sass版本还是免费的, 所以便有了这篇文章来给大家进行了一个分享。
历史文章
- 如何让你的代码更优雅
- 聊聊js中的数组
- 用大白话轻松搞定正则(上)
- 用大白话轻松搞定正则(下)
- 一起学重绘和回流
- js垃圾回收机制原理给你聊的明明白白
- ES11来了,不进来看看嘛
- 秒懂js作用域与作用域链
结束语
以上就是这篇文章的全部内容,希望对大家有帮助,这里不用打赏的哈,大家可以给个赞👍(赞又不要钱),同样也 欢迎大家转发