話很少說,把手拿來。
珍愛生命,遠離後臺。html
在先後端分離模式項目開發過程當中,前端的界面展現、交互邏輯每每須要後臺接口數據支撐,然而萬惡的後臺總跟不上有咱們美麗的前端小姐姐進度。
因而咱們不禁得仰天長嘆,難道就沒有即無需依賴後臺又能完美展現界面數據,即能保證前端交互的完整性又不太費事兒的方法嗎?
答案固然是有的~~~~ 下面就請咱們的主角登場前端
Mock官網首頁是這麼定義的:生成隨機數據,攔截 Ajax 請求。vue
減小開發成本git
先後端分離其實從增長了開發成本,只是在它帶來的優點上可讓咱們忍受這種成本,但攻克這方面成本的目標卻從未中止
剝離先後端開發時的耦合性github
作完本階段的開發詳設以後,前端就能夠開時本階段的開發了,因爲基礎設定已經在詳設階段完成統一,先後端在開發過程當中應該是能夠徹底獨立的。但實際開發中前端每每留着某些接口回執邏輯等着與後臺對接後填充,沒法徹底完成前端自身的界面展現及交互邏輯。而使用mockjs模擬接口及數據前端能夠在最大程度上完全分離開發時與後臺的耦合成本,在開發時就基本完成所有前端邏輯編寫
減小先後端接口對接時間express
先後端完成獨立開發後,就進入了先後臺對接階段,不少項目組就在此階段會花費大量的調試時間及成本。然而實際上,若是前端作完了數據及交互的邏輯,後臺完成了全部接口自測,此階段應該是很是迅速的
前端自建項目演示npm
不少前端開源項目都是無後臺,模擬數據演示的。例如 vue-element-admin, d2-admin, wl-admin.
引入js依賴json
npm install mockjs
在mock/demo.js中寫下以下代碼:axios
import Mock from 'mockjs'
隨機生成一個20-40條的數組數據試試
const projectList = Mock.mock({ "list|20": [{ 'name': '@cname', // 中文名 'account': `@word`, // 英文單詞 'phone': /1[3-9][0-9]{9}/, // 正則模式 'deptName': Mock.mock('@cword(2,4)'), // 隨機2-4字中文單詞 'id': '@guid', // guid }] })
有多種模式可選,具體見官方示例。
有了數據以後,咱們怎麼把數據模擬經過接口返回呢
export default [ { url: '/Api/Project/GetList', type: 'post', response: (res) => { let _fileter_list = []; if(res.body.key){ let _fileter_list = projectList.fileter(i => i.name == res.body.key) } // 沒錯,你應該已經猜到了,res.body就是咱們傳入到接口的數據,咱們能夠在這裏作些邏輯操做 // res包含完整的請求頭信息 return { code: 200, message: "操做成功", data: _fileter_list } // 使用return返回前端須要的數據 } } ... // 多個接口 ]
如今數據有了,咱們如何讓mockjs可以攔截到咱們前端發出的請求,並能準確區分對應接口呢?
在mock/文件夾下再建一個index.js寫咱們mock的監聽邏輯
import Mock from 'mockjs' // 導入mockjs import demoApi from './demo' // 導入咱們模擬數據的js文件 const mocks = [ { intercept: true, // 你可能須要一個開關,來使模擬請求與真實請求並存 fetchs: demoApi }, // 抄來一個解析地址欄參數解析函數 export function param2Obj(url) { const search = url.split('?')[1] if (!search) { return {} } return JSON.parse( '{"' + decodeURIComponent(search) .replace(/"/g, '\\"') .replace(/&/g, '","') .replace(/=/g, '":"') .replace(/\+/g, ' ') + '"}' ) } // 關鍵!抄來一個前端模式構建函數(或者你也能夠建一個mock server) export function mockXHR() { Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send Mock.XHR.prototype.send = function() { if (this.custom.xhr) { this.custom.xhr.withCredentials = this.withCredentials || false if (this.responseType) { this.custom.xhr.responseType = this.responseType } } this.proxy_send(...arguments) } function XHR2ExpressReqWrap(respond) { return function(options) { let result = null if (respond instanceof Function) { const { body, type, url } = options // https://expressjs.com/en/4x/api.html#req result = respond({ method: type, body: JSON.parse(body), query: param2Obj(url) }) } else { result = respond } return Mock.mock(result) } } for (const i of mocks) { if(i.intercept){ for(const fetch of i.fetchs){ Mock.mock(new RegExp(fetch.url), fetch.type || 'get', XHR2ExpressReqWrap(fetch.response)) } } } }
通過上面一通代碼以後,咱們已經初步完成了前端模擬數據的技術條件。
可是你千萬不要忘記了,在main.js引入並使用它哦
import { mockXHR } from '../mock' if(process.env.NODE_ENV == 'development'){ mockXHR(); }
萬事具有,只欠請求,你如今就能夠寫上一個請求試試水了。
axios.post('/Api/Project/GetList').then(res => { console.log(res) })
可是,項目中咱們並不建議你直接就這麼作!
再忍一忍,我們來稍微把請求封裝一下。
src下建一個api文件夾
而後再在src/api/下建一個_request.js
import Axios from "axios"; // 定義axios配置 const http = Axios.create({ baseURL: '', // api的base_url withCredentials: true, // 開啓跨域身份憑證 method: "post", headers: { "Content-Type": "application/json;charset=UTF-8" }, timeout: 5000 // request timeout }); // 設置全局的請求次數,請求的間隙,用於自動再次請求 http.defaults.retry = 2; http.defaults.retryDelay = 1000; // 請求攔截器 http.interceptors.request.use( function (config) { return config; }, function (error) { return Promise.reject(error); } ); // 響應攔截器 http.interceptors.response.use( function (res) { return res; }, function (err) { let config = err.config; let errres = err.response; let err_type = errres ? errres.status : 0; // 收集錯誤信息 switch (err_type) { case 400: err.message = "請求無效"; break; case 401: err.message = "因爲長時間未操做,登陸已超時,請從新登陸"; break; case 403: err.message = "拒絕訪問"; break; case 404: err.message = `請求地址出錯: ${errres.config.url}`; break; case 405: err.message = `未受權`; break; case 408: err.message = "請求超時"; break; case 500: err.message = "服務器內部錯誤"; break; case 501: err.message = "服務未實現"; break; case 502: err.message = "網關錯誤"; break; case 503: err.message = "服務不可用"; break; case 504: err.message = "網關超時"; break; case 505: err.message = "HTTP版本不受支持"; break; default: err.message = "網絡波動,請重試"; } // If config does not exist or the retry option is not set, reject if (!config || !config.retry) return Promise.reject(err); // Set the variable for keeping track of the retry count config.__retryCount = config.__retryCount || 0; // Check if we've maxed out the total number of retries if (config.__retryCount >= config.retry) { // Reject with the error return Promise.reject(err); } // Increase the retry count config.__retryCount += 1; // Create new promise to handle exponential backoff let backoff = new Promise(function (resolve) { setTimeout(function () { resolve(); }, config.retryDelay || 1); }); // Return the promise in which recalls axios to retry the request return backoff.then(function () { return http(config); }); } ); export default http;
封裝了一下axios以後,全部的api接口仍建議統一管理
咱們在api/文件夾下再建一個project.js用來統一管理項目模塊的全部接口
import request from "../_request"; // 1獲取部門列表接口 function getProjectListApi(data) { return request({ url: "/Api/Project/GetList", method: 'post', data }); } // 2添加項目接口 function addProjectApi(data) { return request({ url: "/Api/Project/Add", method: 'post', data }); } // 3刪除項目接口 function delProjectApi(data) { return request({ url: "/Api/Project/Add", method: 'post', data }); } export { getProjectListApi, // 1獲取部門列表接口 addProjectApi, // 2添加項目接口 delProjectApi, // 3刪除項目接口 }
接下來就是最後一步,在咱們開發的.vue文件中使用啦
import { getProjectListApi } from "@/api/project.js"; // 導入用戶列表接口 export default { data(){ return { projectList: [] } }, created(){ this.getProjectList() }, methods: { getProjectList(){ getProjectListApi().then(res => { console.log(res) }) } } }
不出意外的話,通過上面的一系列操做,咱們的數據已經出來啦,mockjs如何在項目中的應用也已經入門完畢,若是你還想被我摸手,就來個人Github交個朋友吧~
Github & segmentfault & 掘金 & csdn & 語雀