您好,登錄后才能下訂單哦!
背景
前端在早期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 中使用正則表達式去匹配路徑即可完成,示例:
即我們只在變量的地方使用正則字符集合去匹配我們的變量。
2.為什么在控制臺里面的 network 中沒有看到我的請求?
剛開始測試時,我查看 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 包裹起來,如下:
結果出現有意思的事情:當請求比較頻繁,在延遲時間內,本次請求得到的響應數據是上次請求的結果。這顯然不是我們希望看到的,而且我們一般是用 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/renewCancel 的 get 請求才會匹配上述規則。
最后建議:get 請求都用正則表達式書寫路徑;post 字符串和正則都行;
總結
mock雖然存在以上所涉及的局限和問題,不過對于日常自測聯調還是很有益處,個人覺得主要還是簡單可行。當然本文所述方式,不僅僅局限在 vue-cli 中,其他框架中亦可按此法進行配置。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。