ming_mock

2021-01-17  本文已影响0人  Minglie

ming_mock

介绍

ming_mock是什么

   ming_mock是[ming_node](https://www.npmjs.com/package/ming_node)的浏览器版本,在浏览器端体验express的开发方式,专注纯前端应用,在前端与后端之间加一层ming_mock,配上丰富的web存储 与 第三方云函数,云数据库更方便的开发纯前端应用,ming_mock是[ming_node](https://www.npmjs.com/package/ming_node)的姐妹篇,强烈建议先学习使用 [ming_node](https://www.npmjs.com/package/ming_node).

mockjs对比

    ming_mock中的mock是指mock服务,而不是mock数据,如果需要mock数据,建议使用[easyMock](https://www.easy-mock.com/) 或 [网易nei](https://nei.netease.com/)或者直接使用mockjs.  ming_mock 相比 mockjs 体积更小(未压缩大约为mockjs 体积的六分之一,40kb,压缩后仅20kb), 支持rest风格, 拥有express相同的开放体验 , 方便的 webSql, json数据库工具等, ming_mock不擅长造假数据,但对 增 删 改 服务的mock要优于mockjs,  ming_mock是专注弱化服务, 纯前端应用类型的开发,而不是用来造假数据。

因为解决查询类的mock方案很多,增删改却很少,ming_mock的内置服务很优雅的解决了增删改类的mock问题。

安装

最新稳定版 v1.9.3
项目主页 GitHub
项目地址 GitHub
npm地址 NPM
更新日志 更新日志
在线测试 https://minglie.github.io

NPM安装

ming_mock无任何第三方依赖,只是一个比较大的js文件.

# 最新稳定版
npm i ming_mock

script引入

实际应用我更多的是用script标签引入

<script src="https://minglie.github.io/js/M_mock.js"></script> 
<script src="https://minglie.gitee.io/mingpage/static/js/M_mock.js"></script> 
#压缩后
<script src="https://minglie.gitee.io/mingpage/static/js/M_mock-min.js"></script> 

ming_mock原理

  ming_mock对jquery进行动态加载判断 内部的极简jquery实现了ming_mock的0依赖,ming_mock结合easyUI是绝配,此时easyUI组件的ajax请求将会被ming_mock拦截,后面介绍如何在ming_mock不影响jquery的ajax的使用, 为了 简化调用 与 异步调用ming_mock会将app注册的所有方法都在MIO对象上再注册一遍, ming_mock同[ming_node](https://www.npmjs.com/package/ming_node)有丰富的过滤器方便公共代码抽取,公共参数的处理或拦截,为了方便调试,ming_mock将所有接口的参数用map存储,从app.reqMap 与app.resMap可以查看某一时刻每个接口最新的请求与响应数据,
image

http请求

ming_mock内部封装了最常用的http请求方法,无需引入其他第三方库

# url 为接口地址,callback 为回调函数, data为请求参数
# get 请求 
M.fetchGet(url, callback, data); 
# post请求
M.fetchPost(url, callback, data);
# post json请求
M.fetchPostJson(url, callback, data);

image.pngimage.png

M.require方法

 M.require是一个简易发出http get请求的方法,内部会自动识别返回的是json,文本还是,js
# 返回json
M.require("https://minglie.github.io/json/minglie.json").then(d=>console.log(d))
# 执行返回的js文件
M.require("https://minglie.github.io/json/minglie.js").then(d=>console.log(d))
# 返回文本
M.require("https://minglie.github.io/json/minglie.txt").then(d=>console.log(d))
image.pngimage.png

M.doSql方法

M.doSql("select * from t_resource").then(d=>console.log(d))
或者
M.doSql("select * from t_resource",(d=>console.log(d)))

M.doSql是直接远程调用后端的app.post("/doSql"),需要后端支持,用ming_node+mysql实现
对应的服务主机地址由M.host配置,默认为空
也可以用M.doSql=M.DB().doSql覆盖
用webSql写页面

var M=require("ming_node");
var mysql  = require('mysql')
 
myDbconfig={
    "host"     : "127.0.0.1",
        "user"     : "root",
        "password" : "123456",
        "port"     : "3306",
        "database" : "guns"
}
var app=M.server();
app.listen(8888);
var Db = {};
var pool = mysql.createPool(myDbconfig);
Db.doSql=function(sql){
    var promise = new Promise(function(reslove,reject){      
        pool.getConnection(function(err, connection){
            connection.query( sql, function(err, rows){
                if(err) {
                    console.error(err);
                    reject(err);
                }else{
                    reslove(rows);
                }
            });
            
            connection.release();
          });
    })
    return promise;
}
 
app.get("/",async function (req,res) {
    app.redirect("/index.html",req,res);
});
 
app.post("/doSql",async function (req,res) {
    try{      
        var rows= await Db.doSql(req.params.sql);
        res.send(M.result(rows));
      
    }catch (e){
        res.send(M.result(e,false));
    }
})
 

M.getParameter

M.getParameter可以方便的获取当前url上的参数,用于页面传参非常方便
M.getParameter("name")

image.pngimage.png

M.urlParse

M.urlParse 实际是内部解析url参数用的,也可用于外部使用


image.pngimage.png

M.fileDownload

M.fileDownload(content, filename) 用于文本文件下载


image.pngimage.png

其他方法

//延时指定毫秒
M.sleep(numberMillis)
//下划线转驼峰,打印"userId"
console.log("user_id".underlineToHump())
//驼峰转下划线,打印"user_id"
console.log("userId".humpToUnderline())
//首字母变大写,打印"User"
console.log("user".firstChartoUpper())
//首字母变小写,打印"uSER"
console.log("USER".firstChartoLower())
//打印当前日期,2019-03-24
console.log(new Date().format("yyyy-MM-dd"))
//随机字符串生成
 M.randomStr()
//对象转form
M.encodeURIComponentObj()

如何在ming_mock中使用$.ajax

最新版的ming_mock,我并没有强行重写 .ajax, 但在easyUI 与 ming_mock 结合时要加一句.ajax=M.ajax;
既想用ming_mock也想用$.ajax 可以用起别名的方式解决

//给apicloud用
window.$1={}
$1.ajax= $.ajax;
//给easyui用
$.ajax=M.ajax;

webpack环境中使用ming_mock

方式1(不建议)

因为这种方式需要npm 安装ming_mock 对原有项目有侵入,故不建议使用
MIO.js 用于写服务

// $ npm install ming_mock
//MIO=M.IO
import  {M, app,MIO} from "ming_mock";
 
app.get("/listAll",function (req,res) {
    console.log("params--->",req.params)
    res.send("AAAAAAAA")
})
export default MIO;

index.js 引入MIO 使用

import React from 'react'
import  MIO from "./MIO.js";

export default class Mockt extends React.Component {
    listAll(id){
        MIO.listAll({id:id}).then((u)=>{
            console.log("<----u",u);
        })
    }
   render(){
        return(
         <div>
            <h1>ming</h1>
            <button onClick={this.listAll.bind(this,77)}>点击</button>
        </div>)
   }
}

方式2(推荐)

index.html模版引入

为了无侵入的使用ming_mock,建议用script方式引入

模版index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://minglie.github.io/js/M_mock.js"></script> 
     <script>
        M.ajaxInterceptorEnable()
        app.get("/listAll",function (req,res) {
                res.send("ww")
        })
     </script>
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

关闭eslink检查或者使用 /* global MIO */

import React from 'react'
/* global MIO */
export default class Mockt extends React.Component {
    listAll(id){
         MIO.listAll({id:44}).then(d=>console.log(d))
    }
   render(){
        return(
         <div>
            <h1>ming</h1>
            <button onClick={this.listAll.bind(this,77)}>点击</button>
        </div>)
   }
}

或使用axios, ming_mock只会拦截app上注册的,也省去了全局变量问题,这种方式完全感知不到ming_mock的存在

import React from 'react'
import axios from 'axios'
/* global MIO */
export default class Mockt extends React.Component {
    listAll(id){
        axios.request({
            method: 'get',
            url: 'https://cdn.liyanhui.com/listAll?id='+id,
        }).then(res => {
            console.log("axios调用", res.data);
        });
    }

    listAll1(id){
        axios.request({
            method: 'get',
            url: 'https://www.fastmock.site/mock/489c97aee272f4fedc398579052ef5eb/ming/api/listAll1?id='+id,
        }).then(res => {
            console.log("axios调用", res.data);
        });
    }
   render(){
        return(
         <div>
            <h1>ming</h1>
            <button onClick={this.listAll.bind(this,77)}>listAll1</button>
            <button onClick={this.listAll1.bind(this,77)}>listAll2</button>
        </div>)
   }
}

普通页面使用ming_mock

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://minglie.github.io/js/M_mock.js"></script>
</head>
<body>
 
<button id="bt1">测试get</button>
<button id="bt2">测试rest</button>
 
<button id="bt3">添加</button>
<button id="bt4">查看</button>
 
<script>
      app.get("/t1",async (req,res)=>{
            console.log(req.params)
            res.send(Promise.resolve(5))
      })
 
      app.get("/t2/:id/:name",async (req,res)=>{
            console.log(req.params)
            res.send(Promise.resolve(req.params.id))
      })
 
      app.post("addUser",async (req,res)=>{
            console.log(req.params)
            M.add({name:req.params.name})
            res.send("add success")
      })
 
      app.get("listByPage",async (req,res)=>{
            console.log(req.params)
            res.send(M.listAll())
      })
 
 
      bt1.onclick=function(){
         a=M.get("/t1?ss=77").then(d=>console.log(" bt1.onclick",d+1))
          console.log(a)
      }
 
      bt2.onclick=function(){
        M.get("/t2/5/zs?ss=7").then(d=>console.log("bt2.onclick",d+1))
      }
 
      a=0;
      bt3.onclick=function(){
        a++;
        MIO.addUser({name:"zs"+a}).then(d=>console.log("bt3.onclick",d+1))
      }
 
      bt4.onclick=function(){
        MIO.listByPage({}).then(d=>console.log("bt4.onclick",d))
      }
 
</script>
 
    
</body>
</html>

内置服务

ming_mock提供了基本的增,删,改,查,分页,条件查询接口可直接使用比如添加接口MIO.add({name:"zs"}),内部随机生成一个ID,可以把这些方法覆盖掉
说明:
app.get("/xxx",(req,res)=>{})或app.post("/xxx",(req,res)=>{})会在M.IO上注册xxx方法, 用M.IO.xxx({})调用xxx方法,方法的参数必须是对象,app.get的回调函数中通过req.params拿到该对象, 这完全是express风格的写法

   app.post("/add",(req,res)=>{
            r=M.add(req.params);
            res.send(M.result(r));
        });
 
        app.get("/delete",(req,res)=>{
            M.deleteById(req.params.id);
            res.send(M.result("ok"));
        });
 
        app.post("/update",(req,res)=>{
            M.update(req.params);
            res.send(M.result("ok"));
        });
 
        app.get("/getById",(req,res)=>{
            r=M.getById(req.params.id);
            res.send(M.result(r));
        });
 
        app.get("/listAll",(req,res)=>{
            r=M.listAll();
            res.send(M.result(r));
        });
 
        app.get("/listByParentId",(req,res)=>{
            r=M.listByProp({parentId:req.params.parentId});
            res.send(M.result(r));
        });
 
        app.get("/listByPage",(req,res)=>{
            r=M.listByPage(req.params.startPage,req.params.limit);
            res.send(M.result(r));
        })

使用ming_mock分析网站接口

来个好玩的,使用ming_mock强大的ajax拦截,可以分析一些单页应用的接口调用信息,以fastMock为例,控制台输入下面脚本,
可以将接口信息发送到自己的服务器;

ajax拦截

拦截ajax请求,将请求信息发送到自己服务端

////////////////////////注入ming_mock脚本//////////////////////////////////////////
var script = document.createElement('script');
script.src = "https://minglie.gitee.io/mingpage/static/js/M_mock.js";
document.getElementsByTagName('head')[0].appendChild(script); 

///////////////开启ajax拦截//////////////////////////////
M.ajaxInterceptorEnable();
//////////////发到自己服务器里///////////////////////////////
M.beforeSend=(options)=>{
   M.fetchGet("http://127.0.0.1:8888/a",()=>{},options);
   return true;
}

/////////////////////服务端/////////////////////////////////////////
app.get("/a", (req, res) => {
    console.log(req.params)
    res.send("https://c-t.work/s/7b10cb04d2754c");
})

image.pngimage.png

SSE反控

浏览器开启SSE监听,服务端反控浏览器,浏览器注入axios就可以控制浏览器发送ajax了

////////////////////////注入ming_mock脚本//////////////////////////////////////////
var script = document.createElement('script');
script.src = "https://minglie.gitee.io/mingpage/static/js/M_mock.js";
document.getElementsByTagName('head')[0].appendChild(script); 

////////////启动本地服务脚本接收拦截的数据///////////////////////////
curl https://gitee.com/minglie/codes/gqruda7entx53y82f6vw077/raw?blob_name=doSql.html >doSql.html 
curl https://minglie.gitee.io/mi/i2.js > index.js && node index.js  

app.get("/a", (req, res) => {
    console.log(req.params)
    res.send("https://c-t.work/s/7b10cb04d2754c");
})

if(Object.keys(M._get).indexOf("/sseServer/")==-1){
   M.sseApp=M.sseServer();
   app.get("/sseServer",M.sseApp)
}

app.get("/p",(req,res)=>{ 
    console.log(req.params);
     M.sseApp.send(JSON.stringify(req.params));
    res.send("ok");
})

app.post("/doSql",(req,res)=>{ 
     console.log(req.params.sql);
     M.sseApp.send(req.params.sql);
     res.send(M.result("ok"));
})

///////////////浏览器端SSE方式反控浏览器//////////////////////////
M.EventSource('http://localhost:8888/sseServer',function(e){
      eval(e.data)
}) 
image.pngimage.png

需要改进点

要改的问题多了以后,一起改

1. app.end() //钩子返回请求的req,否则异步调用无法将请求响应对应上
上一篇 下一篇

猜你喜欢

热点阅读