作前端的應該都知道作頁面的時候,當後端已經定義好了接口,但提供不了數據服務的時候,做爲前端的你搭建頁面是很痛苦的。 爲此搭建一個能夠mock數據的本地服務是頗有必要的。前端
用到的工具庫:json-server提供服務。mockjs提供模擬的數據。node
本文的目錄結構以下:webpack
一、安裝依賴web
npm install json-server mockjs --D
複製代碼
二、編寫db.json路由對應表npm
這是一個api路徑和路徑對應返回的內容組成的一個文件,好比:json
{
"user_info": {
"id": 1000,
"course_name": "馬連白米且",
"autor": "袁明",
"college": "金並即總變史",
"category_Id": 2
}
}
複製代碼
上面的user_info就是你的api接口路徑,後面的value值就是這個接口返回的內容.後端
假如你本地起了一個json-server服務,http://localhost:6666,api
那麼你訪問http://localhost:6666/user_info獲得的就是如下內容:數組
{
"id": 1000,
"course_name": "馬連白米且",
"autor": "袁明",
"college": "金並即總變史",
"category_Id": 2
}
複製代碼
但問題來了: 這樣簡單的定義一個db.json文件,你每次訪問http://localhost:6666/user_info的時候,獲得的都是同一份數據,它不會變。 這不是咱們想要的效果。咱們想要每次訪問都獲得不同的數據。bash
mock/mockDB/test.js
// 引入mock.js
let Mock = require('mockjs');
let Random = Mock.Random;
// 編寫一個函數,這個函數利用mock.js動態生成mock數據
// 我看到不少教程這裏是直接輸出一個對象的,這樣每次訪問獲得的都是一樣的數據。不符合預期,
// 咱們這裏用函數包裝,每次訪問api的時候就執行一次該函數,獲得的就是新的mock數據了
function testList() {
const monitorList = [];
for (var i = 0; i < 3; i++) {
monitorList.push(
Mock.mock({
userid: '25788869998_1562054852076593528',
appid: Random.natural(100, 3000),
content: Random.cparagraph(2, 4),
timestamp: 1562054852,
})
);
}
// 這裏返回你想要的數據格式
return {
success: true,
data: monitorList,
message: '獲取數據成功',
};
}
// 以api路徑爲值,將testList函數暴露出去
exports.user_info = testList;
複製代碼
如上文所說,json-server須要一個json文件作路由配置表,格式以下:
{
"user_info": {
"id": 1000,
"course_name": "馬連白米且",
"autor": "袁明",
"college": "金並即總變史",
"category_Id": 2
}
}
複製代碼
很是注意的是: 路由配置裏,api路徑爲key值,返回的數據爲value值,這個value必須是數組或者對象。不能是函數,下面的寫法是會報錯的。
{
"user_info": function () {
return {
"id": 1000,
"course_name": "馬連白米且",
}
}
}
複製代碼
但想要每次請求同一個接口,返回的都是不同的數據,這個value必須是函數才行。這就是咱們在mock/mockDB/test.js定義的是函數的緣由。由於json-server的原理應該是:拿到訪問的路徑,而後經過路由配置表找到對應的value值,最後返回給用戶的。若是寫死成一個對象,或者數組,那麼每次訪問獲得的都是一樣的數據。
mock/db.js
將mockDB文件夾全部的mock數據文件讀取出來,組裝成上面路由配置表的格式,再暴露出去。 這裏能夠用webpack提供的require.context讀取全部文件,也能夠用node的fs模塊讀取全部文件。這裏我就不展開來寫了。簡單說一下流程。
// 引入mockDB文件夾下的文件,假若有如下文件
let test1 = require('./mockDB/test.js');
let test2 = require('./mockDB/test2.js');
// 這裏定義一個收集的對象
let dbJson = {
func: {},
json: {},
}
// 收集mock函數,在server.js會用到
dbJson.func = {
...test1,
...test2,
};
// 獲取全部的api路徑
let apiPath = Object.keys(dbJson.func);
// 組裝json-server須要的路由表,這裏爲何都是空對象呢?
// 上面說過,路由表的value必須是對象或者數組。但咱們的mockDB文件夾下定義的都是mock函數,因此這裏要保證路由表是正確的,就要從新組裝一份符合格式的路由表。
apiPath.forEach(item => {
dbJson.json[item] = {};
});
exports.dbJson = dbJson.json;
exports.dbFunc = dbJson.func;
複製代碼
const jsonServer = require('json-server');
// 建立json-server實例
const server = jsonServer.create();
const jsonDB = require('./db');
// 將路由配置表傳入,生成路由表
const router = jsonServer.router(jsonDB.dbJson);
const middlewares = jsonServer.defaults();
// 這裏比較重要。
// 目的是:從新定義路由返回的數據。就是說:每訪問一個路由,返回response的時候,均可以通過router.render從新定義response數據
// 由於咱們在db.js裏將mock函數收集到了dbJson.func對象裏。
router.render = (req, res) => {
// 根據請求的url,截取路徑。
// 例如:通常狀況,res.url是/user_info?id=1234這樣的格式。
let end = req.url.indexOf('?');
let apiName = req.url.slice(1, end) || '';
// 根據apiName拿到對應的mock函數,而後返回mock函數生產的mock數據
// 由於每次返回response的時候,都會執行一次該函數,因此獲得的都是新的mock數據
let response = dbJson.func[apiName] && dbJson.func[apiName]();
res.send(response || {}));
};
server.use(middlewares);
// 導入路由
server.use(router);
// 在6666端口開服務
server.listen(6666, () => {
console.log('JSON Server is running');
});
複製代碼
node mock/server.js
複製代碼
這篇文章是我的的實踐作法,若是有說的不對的地方,還望見諒、指正,謝謝