文档章节

mockjs 使用以及反向校验

o
 osc_g8254g7s
发布于 2019/08/19 19:07
字数 1820
阅读 3
收藏 0

精选30+云产品,助力企业轻松上云!>>>

一、背景

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

因此我们需要一种可以帮我们构造数据的工具,并解决以上的若干痛点 mock.js 是一个不错的工具

<a href="https://github.com/QingshanLuoyue/mock-demo" target="_blank" style="color:red">本文 github mock 使用完整例子</a> <br>

二、安装与使用

安装

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
    }]
})

<br>

三、常用构造指令

以下示例可以在 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}/ // 风我齤刘杌菦炧荷岆

<br>

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

#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 就完成了

<br>

五、根据请求的数据修改 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
    }
]
o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
mockjs 使用以及反向校验

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

青S衫%
2019/08/19
0
0
eoLinker-AMS接口管理系统 Mock API教程

基础Mock(简易Mock) eoLinker提供了两种模拟API的方式,基础Mock以及高级Mock,其中基础Mock提供了以下功能: 支持HTTP、HTTPS 支持RESTful风格API 支持对请求方式进行校验(免费版为默认开...

ProLinker
2018/01/24
240
0
腾讯抢金达人项目中的前后端协作

在前后端的协作过程中,通常都是并行开发的状态,那么在后端接口还没有开发完毕时,前端的业务逻辑工作就很难展开。因此也就有很多模拟接口数据的方式,这些方式各有个的优缺点: 直接在代码...

osc_eiwgrws6
04/16
1
0
API文档管理工具折射出的技术视野

什么是技术视野 网上看到不少关于如何提升技术视野的讨论,但却没有人给出定义,到底什么是技术视野? 所谓技术视野,就是看问题时所能切换的不同角(维)度。 下面就以API管理工具(以下简称...

genetalks_大数据
2019/09/30
0
0
vue 用axios实现调用接口下载excel

了解的方式有两种: 1. 用a标签,href设置为后端提供的excel接口 <a href="excel接口">导出</a> 简单方便,缺点就是当有token校验时,不适合 2. 用axios 把token放在请求的header里边 import...

osc_1x3afxmv
2019/03/05
6
0

没有更多内容

加载失败,请刷新页面

加载更多

asp.net core之NLog

NuGet添加 NLog.Web.AspNetCore。 <PackageReference Include="Microsoft.AspNetCore.App" /> 添加配置文件 新建一个文件nlog.config(建议全部小写,linux系统中要注意), 并右键点击其属性......

一介草民Coder
35分钟前
23
0
.NET中的struct和class有什么区别? - What's the difference between struct and class in .NET?

问题: .NET中的struct和class有什么区别? 解决方案: 参考一: https://stackoom.com/question/3OT/NET中的struct和class有什么区别 参考二: https://oldbug.net/q/3OT/What-s-the-differ...

富含淀粉
今天
23
0
android:layout_weight是什么意思? - What does android:layout_weight mean?

问题: I don't understand how to use this attribute. 我不明白如何使用这个属性。 Can anyone tell me more about it? 谁能告诉我更多关于它的事情? 解决方案: 参考一: https://stacko...

javail
今天
17
0
CSS背景不透明度[重复] - CSS Background Opacity [duplicate]

问题: This question already has an answer here: 这个问题已经在这里有了答案: How do I give text or an image a transparent background using CSS? 如何使用CSS为文本或图像提供透明背...

fyin1314
今天
31
0
node http 获取gb2312网页如何转为utf8

最初,我想当然认为是下述做法,但被证明是错误的 const http = require('http'), iconv = require('iconv-lite');const url = 'http://xxx';http.get(url, function(res) { var bo......

高延
今天
24
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部