mock 介紹
mockjs官方使用文件
目的
方便生成隨機資料,攔截Ajax請求。
偶爾會寫一些前端的專案,參考一些比較知名的UI框架,裡面很多例子都會把資料直接寫在裡面,作為參考,因此很多專案裡面也會這樣手寫資料,直接寫死在前端,將程式碼與mock資料緊密結合在一起,每次需要修改資料,都需要直接改動到程式碼層,前端本身改動就非常大,如此頻繁的修改程式碼層面顯然不是很好的實踐。
同時手寫的資料,美觀與真實性差異就看作者水平了。
優點
非常簡單強大,入手快攔截api請求,mock出真實的前後端互動情況更改mock資料方便,與業務程式碼分離,頻繁修改也不會有太大的危險在後端介面準備好前,通過mock介面來模擬與後臺的互動,同時調整資料結構。開發過程中,mock資料也可以與後端提前討論,引導後臺的資料結構更加合理。後臺開發完以後,可以一次性切換介面缺點
靈活性不夠,無法mock後臺一些異常處理返回
Build成靜態檔案以後線上無法使用(或許我沒有找對方法)
comment
針對第一個問題,忽然想到一種方案,或許你可以在同一個接口裡面,mock不同的response,然後採用隨機函式,隨機的返回各種異常response,這樣可以測試前端應對各種後臺error作出的處理是否符合預期。
安裝
cd myProject#僅安裝到本地開發環境npm install mockjs --save-dev
mock 實現
src│ └───api //api資料夾,所有的介面都到單獨抽出來,放在該目錄下│ index.js //入口函式,對外暴露│ search.js //為每一類介面單獨建立的檔案,一類介面統一放在一個目錄下│└───mock index.js //所有的mock api都會寫在下面,如果需要,也可以拆分————————————————
_mock/index.js_
/** * data mock refer to http://mockjs.com * */const Mock = require('mockjs');const util = require('./util');module.exports = function (app) { app.get('/mock/v1/search', function (rep, res) { let result = { "data|24": [{ "date": "@date('yyyy-MM-dd')", "logNum": "@natural(60, 1000)" } ] }; //util.wrapResultSuccess 包裝了response返回,規範統一 res.send(util.wrapResultSuccess(Mock.mock(result).data)); });}
_vue.config.js_
//vue cli3 配置檔案 devServer: { port: port, open: true, host: '127.0.0.1', https: false, hotOnly: false, overlay: { warnings: false, errors: true }, #根據當前環境,把整個mock目錄載入到專案中,每次修改mock檔案需要重啟 before: process.env.ENV == 'mock' ? require('./src/mock'):null, },
_api/index.js_
/** * api interface */import search from '@/api/search'export default { search}
_api/search.js_
/** * article模組介面列表 */import axios from '@/plugins/request';import trend from "@/plugins/handle"const search = { statusPing () { return axios.get(`/status_ping`); }, //search search (body) { return axios.get(`v1/search`, body); },export default search;
utils/request.js
把axiso做了一層封裝,每一次前端請求都會把x-request-id帶給後臺,後臺列印日誌的時候,都會列印這個id,方便日後追蹤問題,同事針對一些後臺的error,可以做一些統一的處理。
import router from '@/pages/login/router';const xss = require("xss");let instance = axios.create({ timeout: 1000 * 60 });instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';function getRandomTraceId() { let characters = 'abcdefghijklmnopqrstuvwxyz1234567890'; let result = ''; let idLength = 32; try { for (let index = 0; index < idLength; index++) { result += characters[parseInt(Math.random() * characters.length, 10)]; } } catch (error) { result = 'getRandomTraceIdError'; } return result;}/** * request interceptor * Before each request, if token exists, carry it in the request header */instance.interceptors.request.use( config => { // console.log(JSON.stringify(config)); //add trace id for request config.headers['x-request-id'] = getRandomTraceId(); //xss filter request url config.url = xss(config.url); // 登入流程控制中,根據本地是否存在token判斷使用者的登入情況 // 但是即使token存在,也有可能token是過期的,所以在每次的請求頭中攜帶token // 後臺根據攜帶的token判斷使用者的登入情況,並返回給我們對應的狀態碼 // 而後我們可以在響應攔截器中,根據狀態碼進行一些統一的操作。 // const token = store.state.token; // token && (config.headers.Authorization = token); return config; }, error => Promise.error(error))instance.interceptors.response.use( res => res.status === 200 ? Promise.resolve(res) : Promise.reject(res), error => { const {response} = error; if (response) { errorHandle(response.status, response.data.message); return Promise.reject(response); } else { // 處理斷網的情況 // eg:請求超時或斷網時,更新state的network狀態 // network狀態在app.vue中控制著一個全域性的斷網提示元件的顯示隱藏 // 關於斷網元件中的重新整理重新獲取資料,會在斷網元件中說明 if (!window.navigator.onLine) { // store.commit('changeNetwork', false); } else { return Promise.reject(error); } } });export default instance;
_main.js_
直接把api類掛載到vue上,這樣方便使用,也可以直接到使用類裡面去引入
import api from '@/api'Vue.prototype.$api = api;window.APP=new Vue({ router, i18n, api, store, render: h => h(App)}).$mount('#app')
_how to use_
async getData(){ let response = await this.$api.search.search(request); if (response.status == 200 && response.data.data) { console.log(`response.data.data = &{response.data.data}`); }}
最新評論