资讯专栏INFORMATION COLUMN

vue-cli 中使用 Mockjs 详解

developerworks / 1162人阅读

摘要:想到函数有延迟网络请求稀释事件延迟执行的效果,于是将模板函数用包裹起来,如下结果出现有意思的事情当请求比较频繁,在延迟时间内,本次请求得到的响应数据是上次请求的结果。

vue-cli 中使用 Mockjs 详解 背景

前端在早期jQuery时代时,前端功能和后端工程基本上都是合在一起,典型的就是常见的maven工程下面的webapp目录包含前端各类静态资源文件。
这个时候,我们总是会遇到这些问题:

老大,接口文档还没输出,我的好多活干不下去啊!

后端小哥,接口写好了没,我要测试啊!

测试时间不够啊,就要发版了,今天难道我有看明天的太阳升起?

诸如种种,就是一句话:劳资,再也不要指望你们了!
node出现之后,准确的说是前后端分离之后,前端迫切需要一种机制,不在需要依赖后端接口开发。经过这几年的发展,有好多大牛在这方面进行了研究。
现在我们终于可以实现真实模拟测试啦。如今天的主角 mockjs

使用详解
1.首先在 src 目录创建 mock 文件夹,定义 mock 主文件 index.js ,在该文件中定义拦截路由配置;
/**
 * 定义本地测试接口,最好与正式接口一致,避免联调阶段修改工作量
 */
// 引入mockjs
import Mock from "mockjs";
// 引入模板函数类
import record from "./presc-record-api";

Mock.setup({
  timeout: 800, // 设置延迟响应,模拟向后端请求数据
});

// Mock.mock( url, post/get , 返回的数据);
Mock.mock(//api/healthPlat/getRecipe/w*/w*/, "get", record.getRecipe);
2.在指定的文件中定义模板函数类,示例:
// 获取 mock.Random 对象
// 引入mockjs
import { Random } from "mockjs";
import Utils from "./Utils";

function getRecipe(req) {
  // mock一组数据
  const data = [];
  for (let i = 0; i < 10; i += 1) {
    const o = {
      recipeId: Random.guid(),
      billId: Random.string(10),
      orgId: Random.string("number", 8, 10),
      viewName: Random.cword(4, 16), // 随机生成任意名称
      personName: Random.cname(),
      reason: Random.csentence(10, 32),
    };
    data.push(o);
  }
  // 返回响应数据对象
  return Utils.setRes(req, {
    data: {
      idCard: Random.id(), // 随机
      details: data,
    },
    totalCount: 20,
  });
}

export default {
  getRecipe,
};
3.在 main.js 中引入 mock/index.js 文件;
// 引入mock文件
import "./mock/index"; // mock 方式,正式发布时,注释掉该处即可

接下来的工作就是配置你的 mock 路由以及模板函数啦。Have Fun!

踩的坑

这里我介绍一下在 vue-cli 中使用 Mockjs 踩到的坑:

1.请求路径包含变量,我该怎么办?

使用过 router 码友知道,我们经常要处理地址中包含参数的路由,此时我们只需要在 Mockjs 中使用正则表达式去匹配路径即可完成,示例:

Mock.mock(//api/healthPlat/getRecipeDetail/w*/w*/, "get", record.getRecipeDetail);

即我们只在变量的地方使用正则字符集合去匹配我们的变量。

2.为什么在控制台里面的 network 中没有看到我的请求?

刚开始测试时,我查看 network 没有看到请求,感到很奇怪!就自问自己几个问题:

为什么在 main.js 入口文件中引入 mockjs 的相关配置文件?

入口文件不都是在 webpack 中被编译,然后在浏览器中执行的吗?

控制台没有拦截到请求,那就是没有拦截到发送到服务器的请求了,对吧?

带着这些问题,阅读源码和文档,发现:

源码中首先查找是否在 Mockjs 中定义了该请求,有则进行拦截,然后使用其模拟请求对象 MockXMLHttpRequest 进行响应,即此时不发送 XHR 请求;

否则使用本地标准 XHR 对象进行请求,此时可以在控制台 network 中看到请求信息

因此,在 main.js 入口文件中引入 mockjs 的相关配置文件,即是在前端代码中加入了 Mockjs 的模拟方式,它将在浏览器中被执行,而不是真正的发送请求,不过我们可以将其打印到控制台进行查看
网友评论可以在服务器中使用 mockjs ,此时就是真是的请求,可以在控制台中查看到请求信息,此处本人未进行相应实践,有兴趣的可以参看 mock-server:

3.使用模板语法,返回的数据里面包含规则“|rules”,导致解析或取值失败,我该怎么办?

刚开始的时候,我按照文档上说的模板语法进行配置,如:

看到属性 code 居然带着规则一起返回了,我说我请求为啥没有解析成功啊,原来 res.code 一直是 undefined ,这是坑啊。
查看源码和可以搜到的网上示例发现:没有使用模板规则的现象,而是使用 mockjs 提供的内置函数来实现,如 .id() .cname() 等等方法。
于是我将mock相关文件中 code 定义改成下面这样:

function  setRes(req, options) {
  window.console.log(req.url);
  const { code = Random.int(0, 5) >= 1 ? 1 : 0, message, data = {}, totalCount = 100 } = options;
  const result = {
    code,
    message: message || ["失败", "错误", "异常"][Random.integer(0, 2)],
    data,
    totalCount,
  };
  window.console.log(result);
  return result;
}

刚开始的时候属性code是这样定义的—— "code|1", true, ,后来改成了 code = Random.boolean(), 发现生成 false 的概览太高了,不适合我们真实的场景。
想到我们只需要增加 code 为 1 的概率,于是本人使用 Random.int(0, 5) 随机生成一个整数,当这个整数大于等于1,我们将 code 设置为 1 ,其他情况为 0 。
也就是说从概率上将,成功的概率为 0.8,失败的概率为 0.2,基本符合我们测试要求,哈哈,机智不^<^。

4.模拟异步请求的过程,发现请求好像是瞬间完成,loading效果没生效

刚开始的时候,没有设置延迟响应,每次请求都好像是瞬间完成的,没有一步操作的那种等待感,没有看到loading罩层出现。
自己debug时,loading罩层是有的,于是想到:请求没有被延迟,而是被同步执行了
想到 lodash.debounce 函数有延迟网络请求、稀释事件、延迟执行的效果,于是将模板函数用 debounce 包裹起来,如下:

Mock.mock("/api/healthPlat/chronicdisease", "get", debounce(record.chronicdisease, 600));

结果出现有意思的事情:当请求比较频繁,在延迟时间内,本次请求得到的响应数据是上次请求的结果。这显然不是我们希望看到的,而且我们一般是用 debounce 的来稀释请求的,用在请求发送之后显然违背了我们的初衷。
翻阅 mockjs 文档,发现作者已经考虑了这个事情。哎,辛苦忙活了大半天,还是要好好看文档啊。具体如下:

Mock.setup({
  timeout: 800, // 设置延迟响应,模拟向后端请求数据
});

5. Mock 无法拦截带参数的 get 请求

刚开始时,发现设置的有些 get 请求总是请求不到 mock 的数据,而有些 get 请求能得到 mock 的数据,post 则不存在这样的问题。非常郁闷!
仔细 debug 时发现:get 请求带参数时失败,找不到路径;get 请求不带参数成功,路径没找到,获取到 mock 的数据;post 路径正确找到,成功得到 mock 数据。
这时突然意思到:get 请求的路径默认后面会加上参数,因此和设置的路径没有匹配上,导致路径没找到,请求失败
于是本人将路径改成正则表达式,就好了。如:

// 刚开始字符串路径,带参数的 get 请求匹配失败
Mock.mock("/api/healthPlat/renewCancel", "get", manage.renewCancel);

改成下面这样就好了:

// 正则表达式路径,带参数的 get 请求匹配成功
Mock.mock(//api/healthPlat/renewCancel/, "get", manage.renewCancel);

但是实际开发过程中,发现上述正则表达式不够完备,如后续我们又另一个路径 /api/healthPlat/renewCancelAddr 也会匹配上述地址,这不是我们希望有的。
此时我们只需改进下正则表达式即可:

// 正则表达式路径,带参数的 get 请求匹配成功
Mock.mock(//api/healthPlat/renewCancel(|?S*)$/, "get", manage.renewCancel);

即只有路径为 /api/healthPlat/renewCancelget 请求才会匹配上述规则。
最后建议:get 请求都用正则表达式书写路径;post 字符串和正则都行;

总结

mock虽然存在以上所涉及的局限和问题,不过对于日常自测联调还是很有益处,个人觉得主要还是简单可行。当然本文所述方式,不仅仅局限在 vue-cli 中,其他框架中亦可按此法进行配置。
上述有不尽之处或是纰漏之处,还望指正,鸣谢!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/8815.html

相关文章

  • vue-cli结合mockjs模拟后台数据

    摘要:在中使用准备工作安装加载模块请求库开始创建文件用于定于接口返回的数据到目录下的任何一个合适的文件夹下,设置好拦截信息,,设置规则可以看官网规则在文件中写入以下模拟数据单条数据多条数据在组件中引入和文件在中运行项目查看控制台以上,结束文 mockjs在vue中使用: 准备工作:1、安装vue-cli2、加载模块mockjs、axios(http请求库)npm install mockjs...

    loostudy 评论0 收藏0
  • 搭建简单的伪热更新Mock服务

    前言 刚开始接触vue-cli,发现用它生成的框架代码是缺少Mock模拟的,于是自己摸索了许久,将自己的摸索的结果通过过程记录下来,希望对别人有所帮助,能少走弯路。 这不是关于vue-cli的,是单纯的模拟数据服务这不是关于vue-cli的,是单纯的模拟数据服务这不是关于vue-cli的,是单纯的模拟数据服务 同时希望获得更好的解决方案,有更好方案的不要吝啬分享啊。 实现目标 1.ajax数据模...

    morgan 评论0 收藏0
  • 浅谈前端mock

    摘要:引言前端开发经常需要等待后端的接口,严重影响了开发效率,我们一般采用方式来避免这个问题。可能会涉及到门技术,分别是服务端技术随机生成特定格式数据的技术请求转发请求拦截。 引言 前端开发经常需要等待后端的接口,严重影响了开发效率,我们一般采用mock方式来避免这个问题。本人参考了大量文章,结合自己的经验,给出自己在mock上的一些理解。 1. 原理 何为mock,我认为mock主要就是通...

    elina 评论0 收藏0
  • 手摸手,带你用vue撸后台 系列五(v4.0新版本)

    摘要:同时增加了单元测试,使用了,增加了可视化配置权限,增加了自定义布局等等,优化了原先的权限方案,支持不刷新页面更新路由等等功能。虽然它的初衷是为了单元测试的,但正好满足了我们的需求。它会重写浏览器的对象,从而才能拦截所有请求,代理到本地。 前言 vue-element-admin 从 2017.04.17提交第一个 commit 以来,维护至今已经有两年多的时间了了,发布了四十多个版本,...

    MonoLog 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<