vue-cli 中使用 Mockjs 詳解

vue-cli 中使用 Mockjs 詳解

背景


前端在早期jQuery時代時,前端功能和後端工程基本上都是合在一塊兒,典型的就是常見的maven工程下面的webapp目錄包含前端各種靜態資源文件。
這個時候,咱們老是會遇到這些問題:前端

  • 老大,接口文檔還沒輸出,個人好多活幹不下去啊!
  • 後端小哥,接口寫好了沒,我要測試啊!
  • 測試時間不夠啊,就要發版了,今天難道我有看明天的太陽升起?

諸如種種,就是一句話:勞資,不再要期望大家了!
node出現以後,準確的說是先後端分離以後,前端迫切須要一種機制,不在須要依賴後端接口開發。通過這幾年的發展,有好多大牛在這方面進行了研究。
如今咱們終於能夠實現真實模擬測試啦。現在天的主角 mockjsvue

使用詳解


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!node

踩的坑


這裏我介紹一下在 vue-cli 中使用 Mockjs 踩到的坑:webpack

1.請求路徑包含變量,我該怎麼辦?

使用過 router 碼友知道,咱們常常要處理地址中包含參數的路由,此時咱們只須要在 Mockjs 中使用正則表達式去匹配路徑便可完成,示例:git

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

即咱們只在變量的地方使用正則字符集合去匹配咱們的變量。github

2.爲何在控制檯裏面的 network 中沒有看到個人請求?

剛開始測試時,我查看 network 沒有看到請求,感到很奇怪!就自問本身幾個問題:web

  • 爲何在 main.js 入口文件中引入 mockjs 的相關配置文件?
  • 入口文件不都是在 webpack 中被編譯,而後在瀏覽器中執行的嗎?
  • 控制檯沒有攔截到請求,那就是沒有攔截到發送到服務器的請求了,對吧?

帶着這些問題,閱讀源碼和文檔,發現:正則表達式

  • 源碼中首先查找是否在 Mockjs 中定義了該請求,有則進行攔截,而後使用其模擬請求對象 MockXMLHttpRequest 進行響應,即此時不發送 XHR 請求;
  • 不然使用本地標準 XHR 對象進行請求,此時能夠在控制檯 network 中看到請求信息

所以,在 main.js 入口文件中引入 mockjs 的相關配置文件,便是在前端代碼中加入了 Mockjs 的模擬方式,它將在瀏覽器中被執行,而不是真正的發送請求,不過咱們能夠將其打印到控制檯進行查看
網友評論能夠在服務器中使用 mockjs ,此時就是真是的請求,能夠在控制檯中查看到請求信息,此處本人未進行相應實踐,有興趣的能夠參看 mock-server: vue-cli

3.使用模板語法,返回的數據裏面包含規則「|rules」,致使解析或取值失敗,我該怎麼辦?

剛開始的時候,我按照文檔上說的模板語法進行配置,如:npm

圖片描述

看到屬性 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 中,其餘框架中亦可按此法進行配置。上述有不盡之處或是紕漏之處,還望指正,鳴謝!

相關文章
相關標籤/搜索