專案實訓 week1 為專案搭建mock.js模擬響應資料
阿新 • • 發佈:2021-07-02
mock.js的用處是增加單元測試的真實性,通過隨機資料,模擬各種場景。不需要修改既有程式碼,就可以攔截 Ajax 請求,返回模擬的響應資料。
最關鍵的一點是不需要等待後端介面,可以自己模擬響應的資料來開發前端
這無疑會給前端開發帶來方便
mock.js的安裝
執行
npm install mockjs
在專案根目錄新建mock資料夾,與package.json同級
在mock資料夾下新建index.js
const Mock = require('mockjs') const { param2Obj } = require('./utils') const test = require('./test') const mocks = [ ...test, ] 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) { Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response)) } } module.exports = { mocks, mockXHR }
為了不讓mock.js每次修改的時候都需要重新打包,我們可以寫一個mock-server熱修改功能
const chokidar = require('chokidar') const bodyParser = require('body-parser') const chalk = require('chalk') const path = require('path') const Mock = require('mockjs') const mockDir = path.join(process.cwd(), 'mock') function registerRoutes(app) { let mockLastIndex const { mocks } = require('./index.js') const mocksForServer = mocks.map(route => { return responseFake(route.url, route.type, route.response) }) for (const mock of mocksForServer) { app[mock.type](mock.url, mock.response) mockLastIndex = app._router.stack.length } const mockRoutesLength = Object.keys(mocksForServer).length return { mockRoutesLength: mockRoutesLength, mockStartIndex: mockLastIndex - mockRoutesLength } } function unregisterRoutes() { Object.keys(require.cache).forEach(i => { if (i.includes(mockDir)) { delete require.cache[require.resolve(i)] } }) } // for mock server const responseFake = (url, type, respond) => { console.log(new RegExp(`/dev-api/${url}`)); return { url:new RegExp(`/dev-api/${url}`), type: type || 'get', response(req, res) { console.log('request invoke:' + req.path) res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond)) } } } module.exports = app => { // parse app.body // https://expressjs.com/en/4x/api.html#req.body app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ extended: true })) const mockRoutes = registerRoutes(app) var mockRoutesLength = mockRoutes.mockRoutesLength var mockStartIndex = mockRoutes.mockStartIndex // watch files, hot reload mock server chokidar.watch(mockDir, { ignored: /mock-server/, ignoreInitial: true }).on('all', (event, path) => { if (event === 'change' || event === 'add') { try { // remove mock routes stack app._router.stack.splice(mockStartIndex, mockRoutesLength) // clear routes cache unregisterRoutes() const mockRoutes = registerRoutes(app) mockRoutesLength = mockRoutes.mockRoutesLength mockStartIndex = mockRoutes.mockStartIndex console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`)) } catch (error) { console.log(chalk.redBright(error)) } } }) }
定義工具類util.js
/** * @param {string} url * @returns {Object} */ function param2Obj(url) { const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') if (!search) { return {} } const obj = {} const searchArr = search.split('&') searchArr.forEach(v => { const index = v.indexOf('=') if (index !== -1) { const name = v.substring(0, index) const val = v.substring(index + 1, v.length) obj[name] = val } }) return obj } module.exports = { param2Obj }
mock.js的使用
我們首先在mock資料夾下編寫test.js,用於測試介面
const testApi1 = {
"userList|10":[
{
"name":"@cname",
"age|18-28":25,
"sex|1":["男","女"],
}],
}
module.exports = [
{
url: 'data/testApi1',
type: 'get',
response: config => {
// const { username } = config.body
// const token = tokens[username]
return {
code: 200,
data: testApi1
}
}
},
]
這裡我們攔截data/testApi1的get請求,並返回資料
資料的格式是隨機生成的10個物件,包含人名、年齡、性別等。
找到request.js,將axios的基本路徑保持和mock-server的監聽基本路徑一致
import axios from 'axios'
export function request(config) {
return new Promise(((resolve, reject) => {
const instance = axios.create({
baseURL: "/dev-api/", //基本路徑
timeout: 1000,
});
instance(config).then(res => {
resolve(res);
}).catch(err => {
reject(err);
})
}))
}
之後修改vue.config.js檔案
module.exports = {
// 輸出目錄
assetsDir: 'static',
devServer: {
port: 8080,
open: true,
overlay: {
warnings: false,
errors: true
},
before: require('./mock/mock-server.js')
},
};
需要新增devServer:{before: }選項,讓mock.js起到攔截作用
最後我們編寫一個請求,模擬向後端請求資料
getData() {
request({
url: 'data/testApi1',
method: 'get',
}).then(res => {
let {code, data} = res.data;
console.log(data);
this.testData = data.userList;
}).catch(err => {
console.log("fail")
});
}