一、背景

  1. 前端开发需要依赖后端接口
  2. 后端接口输出慢、接口规范随时可能会变,而前端毫无感知
  3. 前端需要自己 mock 假数据 json 文件
  4. 假数据 json 数据内容是静态的,测试不同返回情况需要修改 json 文件

    ...

因此我们需要一种可以帮我们构造数据的工具,并解决以上的若干痛点

mock.js 是一个不错的工具

本文 github mock 使用完整例子

二、安装与使用

安装

yarn add mockjs -D

使用

// 使用 Mock
import Mock from 'mockjs'
Mock.mock('http://test.com/getjson.json', 'get', {
// 属性 list 的值是一个数组,其中含有 1 到 10 个元素
'list|1-10': [{
// 属性 id 是一个自增数,起始值为 1,每次增 1
'id|+1': 1
}]
})

三、常用构造指令

以下示例可以在

http://mockjs.com/examples.html

网页上打开控制台

使用Mock.mock({示例代码})查看生成的结果

1、时间戳:

'name|1564577990837-2564577990837': 0

2、id

'name|1-123456789': 0 // 6174430

3、指定长度范围,随机中文字符

name: '@cword(2, 6)' // 价亲三身千然

'name|2-6': '@cword(1)'

4、指定长度范围,随机英文字符

name: '@word(1, 10)' // yyuj

'name|1-10': '@word(1)'

5、http url

name: '@url(http)' // "http://djldfusj.in/ccnknb"

6、生成布尔值,false/true各一半几率

'name|1': true

7、包含小数数字

'name|1-100.3': 1 // 63.895

8、随机选择数组中的元素

'name|1': ['AMD', ''CMD, 'UMD'] // 随机出现数组中的元素

9、万能的正则

(1)时间戳

name: /170\d{10}/ // 1705237332101

(2)小数数字

name: /\d{2}\.\d{3}/ // 78.635

(3)id

name: /\d{1,9}/ // 651866094

(4)英文字符串

name: /\W{1,3}/ // DvX

(5)中文字符串

name: /[\u4e00-\u9fa5]{1,9}/ // 风我齤刘杌菦炧荷岆

四、从零开始完成一个使用例子

#1、创建环境

  1. yarn global add @vue/cli

    1. 安装 vuecli3.x 环境
  2. vue create mock-demo --- 创建项目 mock-demo
    1. 选择 default (babel, eslint)
    2. 选择 Use Yarn
  3. 安装依赖
    1. 安装 axios

      1. yarn add axios
    2. 安装 mockjs
      1. yarn add mockjs -D
  4. 运行项目 yarn serve
    1. 按照命令中显示的项目地址,用浏览器打开

#2、封装 axios

  1. 在 src 下创建 utils 目录,在 utils 下创建 fetch.js 文件
// fetch.js
import axios from 'axios'
export default class baseRequest {
constructor(baseURL) {
baseURL = baseURL || window.location.origin
this.$http = axios.create({
timeout: 30000,
baseURL
})
this.$http.interceptors.request.use(async config => {
return config
})
this.$http.interceptors.response.use(
({ data, config }) => {
if (data.code === 0) {
return data
} else {
return Promise.reject(data)
}
},
e => {
console.log(e, '报错了')
return Promise.reject({
msg: '网络开小差了,请稍后重试'
})
}
)
}
post(url, params = {}, config = {}) {
return this.$http.post(url, params, config)
}
get(url, params = {}, config = {}) {
return this.$http.get(url, {
params,
...config
})
}
}

#3、封装 api 接口

  1. 在 src 下创建 service 目录,在 service 下创建 bilibili-server.js 文件
// bilibili-server.js
// 在本例子中,我们将获取 bilibili 的最近更新番剧接口作为例子
import fetch from '@/utils/fetch.js'
let axios = new fetch()
export const getLastestAnima = () => {
return axios.get('/api/timeline_v2_global')
}

#4、调用获取番剧接口

  1. 在 src 下的 App.vue 文件中,created 生命周期中调用
// App.vue
import HelloWorld from './components/HelloWorld.vue'
import { getLastestAnima } from '@/service/bilibili-server.js'
export default {
name: 'app',
components: {
HelloWorld
},
async created() {
try {
let data = await getLastestAnima()
console.log('getLastestAnima:data:>>>', data)
} catch (error) {
console.log('getLastestAnima:error:>>>', error)
}
}
}

#5、设置代理

  1. 因为跨域限制,所以需要本地设置代理,才能访问 bilibili 的接口
  2. 在项目根目录下创建 vue.config.js 文件
// vue.config.js
module.exports = {
devServer: {
disableHostCheck: true,
open: true, // 是否打开页面
host: '0.0.0.0',
port: 80,
https: false,
hotOnly: true,
proxy: {
'/api': {
target: 'https://bangumi.bilibili.com',
changeOrigin: true
}
}
}
}
  1. 重启项目,然后打开项目,在浏览器控制台可以看到已经将获取到的数据打印出来了

#6、加入 mockjs

1). 在 src 下 创建 mock 目录

2). 在 mock 下创建 index.js 文件,用来注册各个 mock 接口

// /src/mock/index.js
// 使用 Mock
import Mock from 'mockjs'
import modules from './modules' // 注册每个 mock api
for (let key in modules) {
let module = modules[key]
// console.log('module:>>>', module)
Mock.mock(...module)
}

3). 在 mock 下创建 modules,用来分类放置各个微服务相对应的 mock 接口

目录构成

modules
bilibili-server // 微服务
get-lastest-anima.js // mock 接口
index.js // 用来导出每个微服务下的所有 mock 接口
// /src/mock/modules/bilibili-server/get-lastest-anima.js.js

/* eslint-disable no-console */
import { host } from "../../utils/host"
import { formatMockData } from "../../utils/util"
import Mock from "mockjs"
const formatData = formatMockData("", "", "", {
code: 0,
'result|0-100': [
{
'area|1': ["日本", '美国', '国产'],
'arealimit|0-923456789': 0,
'attention|0-923456789': 0,
'bangumi_id|0-923456789': 0,
'bgmcount|1': [/\d{1,6}/, 'SP'],
cover: '@url(http)',
'danmaku_count|0-923456789': 0,
'ep_id|-1-923456789': 0,
'favorites|0-923456789': 0,
'is_finish|1': [0, 1],
'lastupdate|0-1966120600': 0,
'lastupdate_at': '@datetime',
'new|1': true,
'play_count|0-923456789': 0,
pub_time: '@datetime',
'season_id|0-9123456789': 5978,
'season_status|0-9123456789': 13,
'spid|0-9123456789': 0,
square_cover: '@url(http)',
title: "@cword(1,20)",
'viewRank|0-912345678': 0,
'weekday|1': [0, 1, 2, 3, 4, 5, 6]
}
],
message: '@cword(1,10)'
})
let url = host + "/api/timeline_v2_global"
let method = "get"
export default [
url,
method,
function(options) {
console.log("options:>>>", options)
return Mock.mock(formatData)
},
{
url,
method,
formatData
}
]
// /src/mock/modules/index.js
import getLastestAnima from './bilibili-server/get-lastest-anima'
export default {
getLastestAnima
}

4). 在 mock 目录下创建 utils,用来放置工具类

utils
host.js
util.js
// /src/mock/utils/host.js
let h = window.location.origin
export const host = h || ''
// /src/mock/utils/util.js
export const formatMockData = (
mockData = {},
codeStatus = 0,
msg = '@cword(1,10)',
customData
) => {
if (customData) return customData
let initFormatObj = {
code: codeStatus,
result: mockData,
msg: msg
}
return initFormatObj
} // 组合数据
export const comp = function(value) {
return [null, '', value]
}

5). 最后在项目的 main.js 中引入 mock 入口文件

// /src/main.js
import Vue from 'vue'
import App from './App.vue' Vue.config.productionTip = false // 开发环境使用,生产环境注释
import '@/mock' new Vue({
render: h => h(App),
}).$mount('#app')

#7、反向校验后端 api 返回数据

1). 在 mock 目录下的 utils 目录下 创建 proxy-valid.js 文件

// 反向校验后端 api 配置文件
/* eslint-disable no-console */
import Mock from 'mockjs'
import modules from '../modules' export default function(url, method, data) {
Object.keys(modules).forEach(key => {
let ele = modules[key][3]
if (ele && ele.url === url && ele.method === method) {
let validResult = Mock.valid(ele.formatData, data)
// 验证通过,则不用输出信息
if (validResult && validResult.length === 0) {
return
}
console.group(url.replace(/http:\/\//, ''))
console.log('valid response data :>>> url: ', url)
console.log('valid response data :>>> validMsg: ', validResult)
console.groupEnd()
}
})
}

2). 修改 /src/utils/fetch.js

/* eslint-disable no-console */
import axios from 'axios'
// 开发环境使用,打包前注意要注释
import proxyValid from '@/mock/utils/proxy-valid.js'
export default class baseRequest {
constructor(baseURL) {
baseURL = baseURL || window.location.origin
this.$http = axios.create({
timeout: 30000,
baseURL
})
this.$http.interceptors.request.use(async config => {
return config
})
this.$http.interceptors.response.use(
({ data, config }) => {
// 开发环境需要,生产环境需要注释
proxyValid(config.url, config.method, data)
if (data.code === 0) {
return data
} else {
return Promise.reject(data)
}
},
e => {
console.log(e, '报错了')
return Promise.reject({
msg: '网络开小差了,请稍后重试'
})
}
)
}
post(url, params = {}, config = {}) {
return this.$http.post(url, params, config)
}
get(url, params = {}, config = {}) {
return this.$http.get(url, {
params,
...config
})
}
}

此时,一个完整的 数据 mock 和反向校验 demo 就完成了

五、根据请求的数据修改 mock 已经生成的数据

根据前端请求的参数,修改 mock 渲染好的数据,然后返回给前端

这样实现根据不同的参数返回:

1、成功状态

2、失败状态

3、其他异常状态

/* eslint-disable no-console */
import { host } from "../../utils/host"
import { formatMockData } from "../../utils/util"
import Mock from "mockjs"
const formatData = formatMockData("", "", "", {
code: 0,
'result|0-100': [
{
'area|1': ["日本", '美国', '国产'],
'arealimit|0-923456789': 0,
'attention|0-923456789': 0,
'bangumi_id|0-923456789': 0,
'bgmcount|1': [/\d{1,6}/, 'SP'],
cover: '@url(http)',
'danmaku_count|0-923456789': 0,
'ep_id|-1-923456789': 0,
'favorites|0-923456789': 0,
'is_finish|1': [0, 1],
'lastupdate|0-1966120600': 0,
'lastupdate_at': '@datetime', // bilibili 这边返回的接口中,有时候这个属性会少,导致反向校验出错
'new|1': true,
'play_count|0-923456789': 0,
pub_time: '@datetime',
'season_id|0-9123456789': 5978,
'season_status|0-9123456789': 13,
'spid|0-9123456789': 0,
square_cover: '@url(http)',
title: "@cword(1,20)",
'viewRank|0-912345678': 0,
'weekday|1': [0, 1, 2, 3, 4, 5, 6]
}
],
message: '@cword(1,10)'
})
let url = host + "/api/timeline_v2_global"
let method = "get"
export default [
url,
method,
function(options) {
console.log("options:>>>", options)
// options:
// body: null
// type: "GET"
// url: "http://localhost:1385/api/timeline_v2_global"
// 此处 body 就是前端请求的参数集合
// 在此处可以根据 body 里面的参数,来修改 Mock.mock(formatData) 渲染后的数据
// 比如 修改 code = 404
// 设置各种成功、异常状态
return Mock.mock(formatData)
},
{
url,
method,
formatData
}
]

mockjs 使用以及反向校验的更多相关文章

  1. [技术栈]CRC校验原理及C#代码实现CRC16、CRC32计算FCS校验码

    1.CRC.FCS是什么 CRC,全称Cyclic Redundancy Check,中文名称为循环冗余校验,是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检 ...

  2. Modbus协议 CRC 校验码

    CRC(循环冗余校验)在线计算 http://www.ip33.com/crc.html 里面的8005的多项式值,但网上看到的算法都是用A001来异或的 ---------------------- ...

  3. pkg_zhgl

    CREATE OR REPLACE PACKAGE BODY PKG_ZHGL AS --账户管理包 code szn 20110829 --账户管理服务包 --定义本包中需要引用到的常量 --定义说 ...

  4. Vue 项目架构设计与工程化实践

    来源 文中会讲述我从0~1搭建一个前后端分离的vue项目详细过程 Feature: 一套很实用的架构设计 通过 cli 工具生成新项目 通过 cli 工具初始化配置文件 编译源码与自动上传CDN Mo ...

  5. Vue项目架构设计与工程化实践

    摘自Berwin<Vue项目架构设计与工程化实践>github.com/berwin/Blog/issues/14 1.Vue依赖套件 vuex:项目复杂后,用vuex来管理状态 elem ...

  6. CRC32为例详细解析(菜鸟至老鸟进阶)

    CRC-知识解析 cyclic redundancy check 写在前面的话: 之前在做学校项目的时候用到了CRC 原理,但在网上查找的过程中,发现讲解CRC知识的资源很多,但是对新手比较友好的.讲 ...

  7. vue学习(一)项目搭建

    首先需要配置node和npm,如果没有安装的话,百度一下安装教程. 如果感觉npm下载速度慢,可以使用淘宝镜像cnpm,链接地址: http://npm.taobao.org/ 安装cnpm npm ...

  8. Python基础语法一

    所有内容都在代码上,有相关代码注释 # #代表注释 # 区分大小写.以回车换行结束 # 多行编写可以使用反斜杠 \ # 缩进代表一个代码块 #数值 #int类型可以使用下划线分割 c=123_456_ ...

  9. CRC校验源码分析

    这两天做项目,需要用到 CRC 校验.以前没搞过这东东,以为挺简单的.结果看看别人提供的汇编源程序,居然看不懂.花了两天时间研究了一下 CRC 校验,希望我写的这点东西能够帮助和我有同样困惑的朋友节省 ...

随机推荐

  1. Tomcat访问任意磁盘的图片资源

    项目中用户上传的大量图片存放在项目底下带来诸多不便.每次部署项目都需要拷贝出来,防止覆盖掉以前的 图片.容易丢失,前功尽弃.甚至造成经济损失.不可估量. 如何配置tomcat访问图片路径呢?首页你代码 ...

  2. UNP学习第八章udp

    一.基本UDP套接口编程 #include <sys/socket.h> ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, i ...

  3. SCP-bzoj-1085

    项目编号:bzoj-1085 项目等级:Safe 项目描述: 戳这里 特殊收容措施: A*(上下界剪枝). 答案上界:15. 答案下界:当前步数+当前状态剩余步数估价. 这里我们简单地设计估价函数为当 ...

  4. web服务器和后端语言的关系

    1.web服务nginx和php的相互关系  : https://www.cnblogs.com/luckylihuizhou/p/6387171.html 个人理解:web服务器本身没有处理后端语言 ...

  5. 新手指南:DVWA-1.9全级别教程之SQL Injection

    *本文原创作者:lonehand,转载须注明来自FreeBuf.COM 目前,最新的DVWA已经更新到1.9版本(http://www.dvwa.co.uk/),而网上的教程大多停留在旧版本,且没有针 ...

  6. LG1017 进制转换:负数进制

    题目描述 我们可以用这样的方式来表示一个十进制数: 将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数,以10为底数的幂之和的形式.例如:123可表示为 1×102+2×101+3×1001\ ...

  7. PHP的Session机制解析 1

    一.php的默认session机制 php默认用磁盘文件来实现session在php.ini中session.save_handler = files定义session机制session.save_p ...

  8. WEBI更换数据源

    有些时候,我们需要更换数据源.例如切了系统.重新导入数据源,这样我的webi重做的工作量太大.一些变量之类的.替换数据源就很好的解决.不过它应当是对大致80%甚至100%相似的数据源.具体业务具体分析 ...

  9. vue 项目配置 element 出错

    解决方法: 把main.js文件中的 import 'element-ui/lib/theme-default/index.css' 改为 import 'element-ui/lib/theme-c ...

  10. 内核module读取进程页目录

    根据当前CR3寄存器内容,读取对应物理内存中的页目录页,并进行解析 1: void dumpPageDirectoryEntry(u32 entry) 2: { 3: u8 present; 4: u ...