前言:
做前端的应该都知道做页面的时候,当后端已经定义好了接口,但提供不了数据服务的时候,作为前端的你搭建页面是很痛苦的。 为此搭建一个可以mock数据的本地服务是很有必要的。
用到的工具库:json-server提供服务。mockjs提供模拟的数据。
本文的目录结构如下:

一、实践
1、安装依赖
npm install json-server mockjs --D
2、编写db.json路由对应表
这是一个api路径和路径对应返回的内容组成的一个文件,比如:
{
"user_info": {
"id": 1000,
"course_name": "马连白米且",
"autor": "袁明",
"college": "金并即总变史",
"category_Id": 2
}
}
上面的user_info就是你的api接口路径,后面的value值就是这个接口返回的内容.
假如你本地起了一个json-server服务,http://localhost:6666,
那么你访问http://localhost:6666/user_info得到的就是以下内容:
{
"id": 1000,
"course_name": "马连白米且",
"autor": "袁明",
"college": "金并即总变史",
"category_Id": 2
}
但问题来了: 这样简单的定义一个db.json文件,你每次访问http://localhost:6666/user_info的时候,得到的都是同一份数据,它不会变。 这不是我们想要的效果。我们想要每次访问都得到不一样的数据。
3、编写每次都会变化的mock数据
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;
4、编写组装db.json文件的代码
如上文所说,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;
5、搭建json-server本地服务
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');
});
6、启动服务
node mock/server.js
7、结束语
这篇文章是个人的实践做法,如果有说的不对的地方,还望见谅、指正,谢谢