mock数据是前端不变的需求。那怎么才能轻松的本地模拟后端数据。本文通过在npm start的起一个mock服务,前端可通过http请求的方式,获取模拟的json文件的内容。最关键的是,mock可以模拟和后端一样的接口路径,最终只需要改域名地址,就可以实现前端模拟接口和后端接口的无缝切换。本文以vue为例子,讲解前后端如何交互。

原理

利用express起一个服务(端口3618),通过glob库获取json文件的内容,添加到apiContArr数组中,同时用fs.watchFile实现文件的监听,最后通过express里的res.json函数将json内容以json格式传输给前台。

代码

前端代码通过axios这个库,实现restful风格的请求
importaxiosfrom'axios';constfetch=(url,params,method)=>{returnnewPromise((resolve,reject)=>{letajx;if(method==='get'){ajx=axios.get(url,params);}elseif(method==='delete'){ajx=axios.delete(url,params);}elseif(method==='put'){ajx=axios.put(url,params);}else{ajx=axios.post(url,params);}ajx.then(res=>{if(res.code===1){reject(res);}else{resolve(res);}}).catch((err)=>{if(err)returnerr;});});};constdevelopment='http://localhost:3618';constAPI=(url,method)=>params=>fetch(development+url,params,method);// 调用getDemoAPI即可请求数据 exportdefault{getDemoAPI:API('/demo','post');};
后端代码json内容读取和实时监听文件变化
constpath=require('path');constfs=require('fs');constapp=require('express')();constmock=require('mockjs');constglob=require('glob');// 存放所有api内容 letapiContArr=[];asyncfunctioninit(){constapiPath=path.join(__dirname,'./*.json');letapiPathArr=awaitgetPath(apiPath);awaitgetApis();// 监听JSON文件的变化 apiPathArr.forEach(asyncval=>{awaitfs.watchFile(val,curr=>{console.log('API is updated.',curr.mtime);getApis();});});// 将json里的内容添加到apiContArr当中 functiongetApis(){apiPathArr.forEach(asyncval=>{awaitfs.readFile(val,'utf-8',(err,cont)=>{if(err)throwerr;if(!cont)throw'content must exsit.';apiContArr.push(JSON.parse(cont));});});};};init();
读取所有json下的请求,请求地址对应的就是url属性,以此图为例,访问的接口地址就是localhost:3618/demo
注册url服务
app.use((req,res)=>{letdata;letdelay=0;apiContArr.forEach(val=>{val.forEach(reqData=>{if(reqData.regexp){if(!newRegExp(reqData.url).test(req.originalUrl)){returnfalse;}}elseif(req.originalUrl.indexOf(reqData.url)!==0){returnfalse;}letapiRes=reqData.res;data=reqData.mock?mock.mock(apiRes):apiRes;delay=reqData.delay||0;returntrue;});});res.set('Access-Control-Allow-Origin','*');res.set('Access-Control-Allow-Methods','POST, GET, PUT, DELETE, OPTIONS');res.set('Access-Control-Allow-Headers','Origin, X-Requested-With, Content-Type, Accept, Authorization');data!==undefined?setTimeout(()=>res.json(data),delay):res.sendStatus(404);});app.listen('3618',()=>{console.info('Mock server is listening at 3618');});
辅助函数
// 获取某一目录下所有文件名 functiongetPath(path,options={}){returnnewPromise((resolve,reject)=>{glob(path,options,(er,files)=>{if(er){reject(er);}else{resolve(files);}});});};
在package.json中添加mock服务。
{"name":"vue-common-template","version":"1.0.0","description":"common template","author":"carroll","scripts":{"start":"npm run mock | npm run dev","mock":"node mock/app.js"}}

呈现效果

地址