玩转Mock.js:构建模拟数据的利器

玩转Mock.js:构建模拟数据的利器

Mock.js基础介绍

为什么需要Mock.js

  • 对于前后端分离的项目,后端工程师的API数据迟迟没有上线;而前端工程师却没有JSON 数据进行数据填充,自己写后端模拟又太繁重;这个时候,Mock.js 就能解决这个问题,让前端工程师更加独立做自己
    • 前后端分离:让前端攻城师独立于后端进行开发
    • 开发无侵入:不需要修改既有代码,就可以拦截Ajax请求,返回模拟的响应数据
    • 数据类型丰富:支持生成随机的文本、数字、布尔值、日期、邮箱、链接、图片、颜色等
    • 增加单元测试的真实性:通过随机数据,模拟各种场显
    • 用法简单:符合直觉的接口
    • 方便扩展:支持支持扩展更多数据类型,支持自定义函数和正则
  • 原理:通过拦截XMLHttpRequest或fetch等网络请求,根据定义的规则返回模拟的数据。当开发者发起一个请求时,Mock.js会检查匹配的规则,并返回相应的模拟数据。
  • 官方网站为:Mock.js (mockjs.com)

安装与测试

  • Node下运行:创建Mock目录,npm instal mockjs;创建JS文件,键入官网示例代码运行即可输出对应的JSON格式的数据:
js 复制代码
// 使用 Mock
var Mock = require('mockjs')
var data = Mock.mock({
    // 属性 list 的值是一个数组,其中含有 1 到 10 个元素
    'list|1-10': [{
        // 属性 id 是一个自增数,起始值为 1,每次增 1
        'id|+1': 1
    }]
})
// 输出结果 将JavaScript对象转换为格式化的JSON字符串,并在控制台输出,null表示不使用自定义替换函数,4表示缩进为4个空格
console.log(JSON.stringify(data, null, 4))
  • 浏览器运行:直接在HTML文件中引入,编写代码在浏览器打开查看控制台输出:
html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script src="http://mockjs.com/dist/mock.js"></script>
    <script>
        const data = Mock.mock({
            'list|1-10': [{
                'id|+1': 1
            }]
        });
        console.log(data);
        console.log(JSON.stringify(data, null, 4));
    </script>
</body>

</html>

Mock.js语法规范

  • Mock.js的语法规范包括两个部分:数据模板定义规范(DTD)数据占位符定义规范(DPD)
  • 数据模板定义的规范包含3个部分:属性名、生成规则和属性值
json 复制代码
'属性名|生成规则' : 属性值 //'name|rule' : value
  • 其中,字符串、数值有7种生成规则:
生成规则 说明 示例
min-max 生成min~max之间的字符串 'list|1-10'
count 生成count个字符串 'list|5'
min-max.dmin-dmax 生成min~ max之间的浮点数,小数点位数在dmin ~dmax之间 'id|1-10.1-3':1
count.dcount 生成count个字符串,小数点位数为dcount 'id|8.2':1
min-max.dcount //同上
count.dmin-dmax //同上
+step 每次进行累加一个值 'id|+1':1
  • 除了以上几种规则格式,还有布尔值、对象和数组等规则
生成规则 说明 示例
布尔值 生成布尔值,1/2概率true 'flag|1':true
布尔值min-max 生成布尔值,概率为min/(min+max) 'flag|1-10':true
对象count 从对象中随机抽取count个属性 'obj|2':obj
对象min-max 从对象中随机抽取min-max属性 'obj|1-3':obj
数组1 获取1次数组 'arr|1':arr
数组count 重复count次组成新数组 'arr|2':arr
数组+1 累加 'arr|+1':arr
数组min-max 重复min-max次组成新数组 'arr|1-2':arr
  • 支持函数和正则表达式
生成规则 说明 示例
函数 支持函数 'fn|1':function
正则 支持正则 'reg|1'😕[a-z]/
  • 数据定义的占位符@,占领属性值的位置
  • 有两种方式可以输出这种随机占位符:
js 复制代码
console.log(Mock.Random.cname());

console.log(Mock.mock('@cname'));
  • 所有占位符:
Type Method
Basic boolean,natural,integer,float,character,string,range,date,time,datetime,now
Image image,dataImage
Color color
Text paragraph,sentence,word,title,cparagraph,csentence,cword,ctitle
Name first,last,name,cfirst,clast,cname
Web url,domain,email,ip,tld
Address area,region
Helper capitalize,upper,lower,pick,shuffle
Miscellaneous guid,id
js 复制代码
//随机中文人名,不带c就是英文
console.log(Mock.mock('@cname'));
//随机ID
console.log(Mock.mock('@id'));
//随机中文标题,不带c就是英文
console.log(Mock.mock('@ctitle'));
//随机ip地址
console.log(Mock.mock('@ip'));
//随机图片地址
console.log(Mock.mock('@image'));
//随机url地址
console.log(Mock.mock('@url'));
//随机颜色,十六进制
console.log(Mock.mock('@color'));
//随机数值
console.log(Mock.mock('@integer'));
//随机日期
console.log(Mock.mock('@datetime'));
//随机字符串
console.log(Mock.mock('@string'));
  • 如果没有想要的数据格式进行填充,可以使用扩展功能自己扩展:
js 复制代码
//自行扩展占位符
Mock.Random.extend({
    cstore() {
        return this.pick([
            '宠物店',
            '美容店',
            '小吃店',
            '数码店',
            '快餐店'
        ]);
    }
});

console.log(Mock.mock('@cstore'));

Axios快速实践

  • axios.js是一个基于promise的HTTP库,支持浏览器·和Node环境;可以使用这个库来执行Ajax请求,获取JSON数据;可以利用axios发送get、post等一系列请求,然后得到数据
  • 安装:
  • 简单的在Node环境下实现远程获取json数据:
js 复制代码
const axios = require('axios');

axios.get('url')
     .then(res => {
          console.log(res.data);
     })
     .catch(err => {
          console.log('错误' + err);
     });
  • 有时候需要在url地址配置参数进行数据筛选:
js 复制代码
axios({
    method : 'get',
    url : 'url',
    params : {
        id : 1,
        status : 5
    }
}).then(res => {
    console.log(res.data);
});
  • 如果项目中产生多个异步请求,会根据耗时长短来执行;如果需要请求按指定的顺序执行,使用all()方法:
js 复制代码
axios.all([
    axios({
        url : 'url',
        data : '1.异步'
    }),
    axios({
        url : 'url',
        data : '2.异步'
    }),
    axios({
        url : 'url',
        data : '3.异步'
    }),
]).then(axios.spread((res1, res2, res3) => {
    console.log(res1.config.data);
    console.log(res2.config.data);
    console.log(res3.config.data);
}));
  • 实例化操作与拦截操作:
js 复制代码
const myAxios = axios.create();
myAxios.defaults.baseURL = 'url';

//请求拦截
myAxios.interceptors.request.use(config => {
    //打印,修改
    console.log('loading...');
    //config.url = '/data2.json';
    //config.timeout = 50;
    return config;
});

//响应拦截
myAxios.interceptors.response.use(response => {
    //修改返回数据的格式
    return response.data;
});

myAxios.request({
    method : 'get',
    url : '/data.json',
}).then(res => {
    console.log(res);
});

Mock拦截axios请求

Mock.mock

  • 假设axios异步请求的数据尚未上线或不全,然后通过mock请求拦截,随机生成填充的数据进行前端设计
js 复制代码
//ajax
axios.request({
    method : 'get',
    url : 'url'
}).then(res => {
    console.log(res.data);
});

//mock拦截
Mock.mock('url', {
    'list|5-10' : [
        {
            'id|+1' : 1,
            'username' : '@cname',
            'email' : '@email',
            'gender' : '@boolean',
            'price' : '@integer'
        }
    ]
});

Mock.setup

  • 使用Mock拦截请求时,可以通过Mock.setup()配置进行特定的行为:
js 复制代码
//响应时间为400毫秒(默认值是10-100)
Mock.setup({
    timeout: 400
})
// 响应时间介于200-600毫秒之间
Mock.setup({
    timeout: '200-600'
})
  • 注:目前,接口 Mock.setup( settings ) 仅用于配置 Ajax 请求,将来可能用于配置 Mock 的其他行为。

Mock.valid

  • 校验真实数据 data 是否与数据模板 template 匹配。
js 复制代码
var template = {
    name: 'value1'
}
var data = {
    name: 'value2'
}

Mock.valid(template, data)

// =>
[
    {
        "path": [
            "data",
            "name"
        ],
        "type": "value",
        "actual": "value2",
        "expected": "value1",
        "action": "equal to",
        "message": "[VALUE] Expect ROOT.name'value is equal to value1, but is value2"
    }
]

Mock.toJSONSchema

  • 把 Mock.js 风格的数据模板 template 转换成 JSON Schema
js 复制代码
const Mock = require('mockjs');

// 创建一个 Mock 对象
const mockData = Mock.mock({
    'list|1-10': [{
        'id|+1': 1,
        'name': '@cname',
        'age|18-60': 1
    }]
});

// 将 Mock 对象转换为 JSON Schema
const jsonSchema = Mock.toJSONSchema(mockData);

console.log(jsonSchema);

Mock在Vue项目实践

  • 创建好Vue项目,npm install mockjs安装mockjs包
  1. 新建.env.development,定义环境变量:
md 复制代码
# 控制是否需要使用mock模拟的数据
MOCK = TRUE
  1. 定义接口路由,在接口中并返回mock模拟的数据;在项目文件创建mock文件夹,定义index.js文件:
js 复制代码
const Mock = require('mockjs')

module.exports = function (app) {

    if (process.env.MOCK == 'true') {
        // node中的express框架
        // 参数1: 接口地址;参数2:服务器处理函数
        app.use('/api/userinfo', (req, res) => {
            // 随机生成一个对象
            var data = Mock.mock({
                id: '@id',
                username: '@cname',
                date: '@date(yyyy-MM-dd)',
                description: '@paragraph',
                email: '@email',
                'age|18-40': 0
            })
            // 将模拟的数据转成json格式返回给浏览器
            res.json(data)
        })
    }
}
  1. 在vue.config.js中配置devServer,在before属性中引入接口路由函数:
js 复制代码
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  devServer: {
    // devServer在发送请求时,会先走到before指定的函数中进行处理,如果before中没有对应的接口路由,才会请求外网等
    onBeforeSetupMiddleware: require('./mock/index.js')
  }
})

3.使用axios调用该接口,获取数据:

vue 复制代码
<template>
  <div id="app">
    <h1>Test</h1>
  </div>
</template>

<script>
import axios from "axios";

export default {
  created() {
    axios.get('/api/userinfo').then(res => {
      console.log(res);
    })
  }
}
</script>

<style></style>

总结与思维拓展

主流Mock方案对比

  • 代码侵入:

    • 直接在本地写死或者导入本地json数据文件
    • 优点:简单快捷
    • 缺点:冗余代码过多,需要一一剔除
  • 抓包工具:

    • 使用抓包工具对网络请求进行拦截,将其替换成我们需要的Mock数据
    • 优点:真实性强
    • 缺点:操作繁琐,成本较高
  • 本地服务:

    • 使用express或者koa等框架编写后端接口

    • 优点:真实,方便管理

    • 缺点:前端 === 全栈 ?

  • 浏览器插件:

    • 运行与浏览器,避免了本地部署和使用第三发的服务
    • 优点:方便快捷
    • 缺点:?
    • 注:这里笔者进行了一下实践,个人认为也是一种比较轻量级的快速上手方案,详情参考:一款好用的 Chrome Mock 插件 - 掘金 (juejin.cn)
  • 平台类:

    • 使用软件或者网页来进行接口管理模拟数据
    • 优点:全面快捷
    • 缺点:依赖后端,需要(maybe)收费
  • 请求拦截:

    • 通过拦截 XMLHttpRequest 或 fetch 等网络请求,然后根据自定义规则返回 mock 数据
    • 优点:不在依赖后端,直接拦截请求,数据真实
    • 缺点:一定的学习成本?
相关推荐
还是大剑师兰特13 分钟前
什么是尾调用,使用尾调用有什么好处?
javascript·大剑师·尾调用
Watermelo61734 分钟前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
一个处女座的程序猿O(∩_∩)O3 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
燃先生._.9 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖10 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
black^sugar11 小时前
纯前端实现更新检测
开发语言·前端·javascript
2401_8576009512 小时前
SSM 与 Vue 共筑电脑测评系统:精准洞察电脑世界
前端·javascript·vue.js
2401_8576009512 小时前
数字时代的医疗挂号变革:SSM+Vue 系统设计与实现之道
前端·javascript·vue.js
GDAL12 小时前
vue入门教程:组件透传 Attributes
前端·javascript·vue.js