前言:
前后端分离的协作模式下,前后端数据传输都是基于http接口实现的,显然前端的开发是依赖后端接口实现的。在讲求快速迭代的互联网公司这种串行的等待肯定是不会出现的。前后端约定好接口的出参和入参之后,前端数据模拟(mock)就很有必要了。前端基于接口文档自己模拟一份假数据作为前端的数据源。后端按照约定的文档实现接口功能。
mock实现有几种方式:
- 在前端项目写死本地数据
- 前端项目中建立mock文件,随机生成参数
- Mock Server 的方式进行数据模拟
一、在前端项目写死本地数据:
在前端写死数据,是最简单的实现方式,前端通常将某个接口的动作封装到一个方法里,调用的时候直接返回写死的数据。
async getData(){ // 开发阶段不走接口直接返回本地mock数据。 return await new Promise(function(resolve){ setTimeout(()=>{ resolve({code:0, message: 'success', data: {}}) }, 200) }) // 真实的请求 return await axios.get('/api/getUserInfo'); }
这种方法在接口比较少的情况下,使用会比较合适,不然大量的json数据定义,很麻烦!
二、前端项目中建立mock文件,使用mock随机生成参数
1、安装mockjs
使用npm安装:npm install mockjs;
或直接<script src="http://mockjs.com/dist/mock.js"></script>;
2、在根目录下新建mock文件夹,在mock文件夹下新建util.js
- mockDom/ - mock/ - util.js
3、编辑util.js
const Mock = require("mockjs"); let data = Mock.mock({ "data|10": [ //生成100条数据 数组 { "id|+1": 1, //生成商品id,自增1 "detail": "@ctitle(10)", //生成商品信息,长度为10个汉字 "name": "@cname", //生成商品名 , 都是中国人的名字 "phone": /^1(5|3|7|8)[0-9]{9}$/, //生成随机电话号 "price|30-1000": 30, //随机生成商品价格 在30-1000之间 "img": "@Image(‘100x40‘,‘#c33‘, ‘#ffffff‘,‘小北鼻‘)", //生成随机图片,大小/背景色/字体颜色/文字信息 } ] }) Mock.mock(/goods\/goodAll/, 'post', () => { //三个参数。第一个路径,第二个请求方式post/get,第三个回调,返回值 return data })
4、模拟完数据后,需要在入口主文件 entry.js中 引入这个模拟数据的文件
// 引入配置好的mockjs import '../mock/util.js';
5、页面调用接口(这里为了便捷,使用axios调用,但是你也可以用ajax调用)
import axios from "axios"; mounted: () { this.initData(); }, methods:{ initData(){ axios.post("http://localhost:8080/goods/goodAll").then((res)=>{ console.log(res) }) } }
三、Mock Server 的方式进行数据模拟
我们为什么选择这种方式?
拦截请求替换成我们准备好的mock数据,这样做对我们代码无侵入型,缺点就是配置繁琐,不便于复用。
Mock Server实现需要3部分:node服务、路由、数据模拟
1、第一步使用express搭建node项目
执行语句:
npm init
一直回车键即可,生成package.json
2、第二步配置express及路由
在根目录下新建index.js
-mockServer/ - index.js - package.json
下载: express
npm i express -S
编辑index.js
var express = require('express'); var app = express(); app.get('/', function(req, res) { res.send('Hello World!'); }); var server = app.listen(3000, function() { var host = server.address().address; var port = server.address().port; console.log('Example app listening at http://%s:%s', host, port); });
控制台运行:
node index.js
3、第三步,写死数据模拟接口
在根目录下,新建mock文件夹和server.js文件
-mockServer/ - mock/ - server.js - index.js - package.json
执行下载所需包:
npm i body-parser connect-multiparty -S
编辑server.js
const express = require("express"); const bodyParser = require("body-parser"); const multipart = require("connect-multiparty"); const multipartMiddleware = multipart(); const app = express(); // 定义mock方法 const mock = (data, params) => { if (Object.prototype.toString.call(data) === "[object Object]") { return data; } else if (typeof data === "function") { return data(params); } else { return "error: data shold be an object or a function."; } }; // mock数据 const getUserInfo = { code: 0, message: "success", data: { name: "Alice", mobile: "182xxxx9999", age: 30 } } const testData = { code: 0, message: "success", data: { id: 1, name: "test" } } // 路由和数据的聚合 const config = [{ method: "get", url: '/api/getUserInfo', data: getUserInfo }, { method: "post", url: '/api/test', data: getUserInfo }]; app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); // 绑定路由信息 config.forEach(({ method, url, data }) => { if (method === "get") { app.get(url, (req, res) => { res.json(mock(data, req.query)); }); } else if (method === "post") { app.post(url, multipartMiddleware, (req, res) => { res.json(mock(data, req.body)); }); } else if (method === "jsonp") { app.get(url, (req, res) => { const query = req.query; const mockData = JSON.stringify(mock(data, req.query)); const callback = "typeof " + query.callback + ' === "function" && ' + query.callback + "(" + mockData + ")"; res.send(callback); }); } }); // 支持自定义端口 let port = 8081; process.argv.forEach((arg, index, arr) => { console.log("arg----------", arg); if (arg === "--port") { port = arr[index + 1] || 8081; return false; } }); module.exports = app.listen(port, () => { console.log("Mock Server listening on http://localhost:" + port); });
引入到index.js(需要将index.js文件清空,避免冲突)
var server = require("./mock/server.js")
运行项目:
node index.js
浏览器访问:http://localhost:8081/api/getUserInfo ,能访问到数据说明我们的接口已经写好了,在你的前端项目调用即可。
4、第四步使用 Mock.js 造假数据,拆分模块
下载mockjs
$ npm i mockjs -S
mock下面添加api文件夹
-mockServer/ - mock/ - config.js - server.js - api/ - getUserInfo.js - testData.js - index.js - package.json
最终文件代码:
getUserInfo.js
module.exports = { "code": 0, "message": "success", "data": { "name": "@cname", "mobile": /^1[385]\d{9}$/, "age|18-50": 1, "orders|5-10": [{ "id": "@id", "from": "@county(true)", "to": "@county(true)" }] } }
testData.js
module.exports = { "ret": true, "data|1-10": [{ "userid": "@id()", "username": "@cname()", "date": "@date()", "avatar": "@image('200x200','red','#fff','avatar')", "description": "@paragraph()", "ip": "@ip()", "email": "@email()" }] }
config.js
// 路由和数据的聚合 module.exports = [{ method: "get", url: '/api/getUserInfo', data: require("./api/getUserInfo") }, { method: "post", url: '/api/test', data: require("./api/testData") }];
server.js
const express = require("express"); const bodyParser = require("body-parser"); const multipart = require("connect-multiparty"); const Mock = require("mockjs"); const multipartMiddleware = multipart(); const app = express(); // 定义mock方法 const mock = (data, params) => { if (Object.prototype.toString.call(data) === "[object Object]") { return Mock.mock(data); } else if (typeof data === "function") { return Mock.mock(data(params)); } else { return "error: data shold be an object or a function."; } }; // 路由和数据的聚合 const config = require("./config") app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); // 绑定路由信息 config.forEach(({ method, url, data }) => { if (method === "get") { app.get(url, (req, res) => { res.json(mock(data, req.query)); }); } else if (method === "post") { app.post(url, multipartMiddleware, (req, res) => { res.json(mock(data, req.body)); }); } else if (method === "jsonp") { app.get(url, (req, res) => { const query = req.query; const mockData = JSON.stringify(mock(data, req.query)); const callback = "typeof " + query.callback + ' === "function" && ' + query.callback + "(" + mockData + ")"; res.send(callback); }); } }); // 支持自定义端口 let port = 8081; process.argv.forEach((arg, index, arr) => { if (arg === "--port") { port = arr[index + 1] || 8081; return false; } }); module.exports = app.listen(port, () => { console.log("Mock Server listening on http://localhost:" + port); });
index.js
var server = require("./mock/server.js");
四、安装supervisor
最后你会发现我们每一次改变文件都需要执行一遍node index.js ,这样做是真的很麻烦啊,我们可以借助工具,在你本地安装supervisor
$ npm i supervisor -g
使用supervisor执行命令,开启项目,这样你每次更新项目supervisor都会监听到,自动运行项目
supervisor --harmony index
五、github路径:https://github.com/luxueyan1314/mockServer
转载请注明:流年似水 » 前端工程化-搭建本地 Mock 服务