读取模拟服务器的静态数据,读取模拟服务器动态数据。
一、准备工作
1、参考文档
json-server官网
mockjs官网
2、安装包
# 安装json-server服务 npm install json-server --save-dev
# 安装nodemon,修改配置无需重启服务 npm install nodemon --save-dev
# 安装批量生成数据 npm install mockjs --save-dev
3、mock目录结构
|--dynamic //动态数据方式 |--config.js //配置文件 |--db.js //动态数据文件 |--routes.js //路由规则 |--server.js //服务文件 |--static //静态数据方式 |--config.js //配置文件 |--db.js //静态数据文件 |--routes.js //路由规则 |--server.js //服务文件
4、给package.json添加配置
"scripts": { "server": "cd mock/static && nodemon server.js", "dserver": "cd mock/dynamic && nodemon server.js" }
5、webpack配置(代理,接口路由匹配)
// 本地开发 Server 配置 const DEV_SERVER_CONFIG = { historyApiFallback: true, hot: true, inline: true, progress: true, host: '127.0.0.1', open: true, overlay: true, proxy: { '/api/*': { // 静态 target: 'http://127.0.0.1:3005', secure: true, changeOrigin: true }, /*'/api/*': { // 动态 target: 'http://127.0.0.1:3003', secure: true, changeOrigin: true }*/ } };
二、模拟从服务器读取数据-静态数据
1、文件调用依赖结构图
2、mock配置文件
// config.js module.exports = { SERVER: '127.0.0.1', //定义端口号 PORT: 3005 };
// db.js /** * 数据模块 * 目标是把不同页面的变量和数据之间的映射集合到一个对象。 * 某页面 { getList: { message: null, data: [Array], success: true, all: 3 }, deleteItem: { message: null, data: null, success: true, all: 0 } } * 大集合 { getList: { message: null, data: [Array], success: true, all: 3 }, deleteItem: { message: null, data: null, success: true, all: 0 } } */ // 引入需要mock数据的页面接口配置 let demoA = require('../../demos/staticDataA/fakeData/index.js'); let demoB = require('../../demos/staticDataB/fakeData/index.js'); const dataMaps = [demoA, demoB]; const mergeObject = (dMaps = []) => { return Object.assign(...dMaps); }; const dataObj = mergeObject(dataMaps); module.exports = dataObj;
// routes.js /** * 路由模块 * 目标是把变量和接口地址之间的映射转换成路由映射表 * 变量和接口地址间的映射 { api: { getList: 'api/list', deleteItem: 'api/delete' } }; * 路由映射表 { '/api/list*': '/getList', '/api/delete*': '/deleteItem' } */ // 引入需要mock数据的页面接口配置 let demoA = require('../../demos/staticDataA/interfaceUrl.js'); let demoB = require('../../demos/staticDataB/interfaceUrl.js'); const interfaceMaps = [demoA, demoB]; const swapKeyValue = (iMaps = []) => { return iMaps.reduce((previousValue, currentValue) => { // 解构出api里面的配置 let { api } = currentValue; for (let key in api) { // key和value对调 previousValue[`/${api[key]}*`] = `/${key}`; } return previousValue; }, {}); }; const routeMap = swapKeyValue(interfaceMaps); module.exports = routeMap;
// server.js const config = require('./config.js'); const jsonServer = require('json-server'); const rules = require('./routes.js'); const dbfile = require('./db.js'); const ip = config.SERVER; const port = config.PORT; const server = jsonServer.create(); const router = jsonServer.router(dbfile); const rewriter = jsonServer.rewriter(rules); const middlewares = jsonServer.defaults(); server.use(jsonServer.bodyParser); server.use(middlewares); // 添加响应头 server.use((req, res, next) => { res.header('X-Server', 'jsonServer-mockjs'); next(); }); server.use(rewriter); server.use(router); server.listen({ host: ip, port: port }, function() { console.log(JSON.stringify(jsonServer)); console.log(`JSON Server is running in http://${ip}:${port}`); });
3、页面模块
// 目录树 │ ├── staticDataA │ │ ├── fakeData │ │ │ ├── deleteItem.js │ │ │ ├── getList.js │ │ │ └── index.js │ │ ├── interfaceUrl.js │ │ └── staticDataA.jsx │ └── staticDataB │ ├── fakeData │ │ ├── getBookList.js │ │ ├── index.js │ │ └── updateItem.js │ ├── interfaceUrl.js │ └── staticDataB.jsx
// getList.js module.exports = function() { return { 'success': true, 'data': [{ 'id': '001', 'name': 'banana' }, { 'id': '002', 'name': 'orange' }, { 'id': '003', 'name': 'apple' } ] }; };
// index.js let getList = require('./getList.js'); let deleteItem = require('./deleteItem.js'); module.exports = { getList: getList(), deleteItem: deleteItem() };
// interfaceUrl.js // 既用于本地模拟接口,也用于读取真正的后端接口。 module.exports = { api: { getList: 'api/list', deleteItem: 'api/delete' } };
4、启动页面和服务(记得切换webpack的代理配置)
# 启动服务 npm run server npm run dev 打开浏览器,在地址栏中输入http://localhost:3005/
三、模拟从服务器读取数据-动态数据
1、mock配置文件
// config.js
module.exports = {
SERVER:"127.0.0.1",
//定义端口号
PORT: 3003
};
// db.js
/** * 数据模块 * 目标是把不同页面的变量和数据之间的映射集合到一个对象。 * 某页面 { getList: { message: null, data: [Array], success: true, all: 3 }, deleteItem: { message: null, data: null, success: true, all: 0 } } * 大集合 { getList: { message: null, data: [Array], success: true, all: 3 }, deleteItem: { message: null, data: null, success: true, all: 0 } } */ // 引入需要mock数据的页面接口配置 let demoA = require('../../demos/dynamicDataA/fakeData/index.js'); let demoB = require('../../demos/dynamicDataB/fakeData/index.js'); const dataMaps = [demoA, demoB]; const mergeObject = (dMaps = []) => { return Object.assign(...dMaps); }; const dataObj = mergeObject(dataMaps); module.exports = dataObj;
// routes.js /** * 路由模块 * 目标是把变量和接口地址之间的映射转换成路由映射表 * 变量和接口地址间的映射 { api: { getList: 'api/list', deleteItem: 'api/delete' } }; * 路由映射表 { '/api/list*': '/getList', '/api/delete*': '/deleteItem' } */ // 引入需要mock数据的页面接口配置 let demoA = require('../../demos/dynamicDataA/interfaceUrl.js'); let demoB = require('../../demos/dynamicDataB/interfaceUrl.js'); const interfaceMaps = [demoA, demoB]; const swapKeyValue = (iMaps = []) => { return iMaps.reduce((previousValue, currentValue) => { // 解构出api里面的配置 let { api } = currentValue; for (let key in api) { // key和value对调 previousValue[`/${api[key]}*`] = `/${key}`; } return previousValue; }, {}); }; const routeMap = swapKeyValue(interfaceMaps); module.exports = routeMap;
// server.js const config = require('./config.js'); const jsonServer = require('json-server'); const rules = require('./routes.js'); const dbfile = require('./db.js'); const ip = config.SERVER; const port = config.PORT; const server = jsonServer.create(); const router = jsonServer.router(dbfile); const rewriter = jsonServer.rewriter(rules); const middlewares = jsonServer.defaults(); server.use(jsonServer.bodyParser); server.use(middlewares); // 添加响应头 server.use((req, res, next) => { res.header('X-Server', 'jsonServer-mockjs'); next(); }); server.use(rewriter); server.use(router); server.listen({ host: ip, port: port }, function() { console.log(JSON.stringify(jsonServer)); console.log(`JSON Server is running in http://${ip}:${port}`); });
2、页面模块
// 目录树 ├── demos │ ├── dynamicDataA │ │ ├── dynamicDataA.jsx │ │ ├── fakeData │ │ │ ├── getNewsA.js │ │ │ └── index.js │ │ └── interfaceUrl.js │ ├── dynamicDataB │ │ ├── dynamicDataB.jsx │ │ ├── fakeData │ │ │ ├── getNewsB.js │ │ │ └── index.js │ │ └── interfaceUrl.js
// getNewsA.js let Mock = require('mockjs'); let Random = Mock.Random; module.exports = function() { var data = { news: [] }; for (var i = 0; i < 10; i++) { var content = Random.cparagraph(0, 10); data.news.push({ id: i, title: Random.cword(8, 20), desc: content.substr(0, 40) }); } return { 'success': true, 'data': data }; };
// index.js let getNewsA = require('./getNewsA.js'); module.exports = { getNewsA: getNewsA() };
// interfaceUrl.js // 既用于本地模拟接口,也用于读取真正的后端接口。 module.exports = { api: { getNewsA: 'api/newsListA' } };
3、启动服务和页面
# 启动服务
npm run dserver
npm run dev
打开浏览器,在地址栏中输入http://localhost:3003/
四、规范制度
本着少踩坑的原则,下面约束一些fakeData中的开发规范。
1、mock多模块,文件命名应该不一致。
比如A模块是staticDataA/fakeData/getList.js,B模块是staticDataB/fakeData/getBookList.js。
2、不同模块,key命名要不同。
比如A模块是demos/staticDataA/fakeData/index.js,key有getList和deleteItem。
比如B模块是demos/staticDataB/fakeData/index.js,key有getBookList和updateItem。
3、文件名和变量名保持一致
比如 let getList = require('./getList.js');
4、同一模块,key命名要一致。
比如A模块的staticDataA/fakeData/index.js文件的key为getList,staticDataA/interfaceUrl.js文件的key为getList,也就是说数据映射变量和路由映射变量需要保持一致。