在项目中使用mockjs

一、了解mockjs

前言:mockjs是什么

生成随机数据,拦截 Ajax 请求。

通过随机数据,模拟各种场景;不需要修改既有代码,就可以拦截 Ajax 请求,返回模拟的响应数据;支持生成随机的文本、数字、布尔值、日期、邮箱、链接、图片、颜色等;支持支持扩展更多数据类型,支持自定义函数和正则。

优点是非常简单方便, 无侵入性, 基本覆盖常用的接口数据类型.

1.安装

npm install mockjs

2.引用

var Mock = require('mockjs')    //普通引用方式

import Mock from 'mockjs'      //在vue中可以这样引用

3.使用

testMockJs(){
    let data = Mock.mock({ 
        'list|1-10':[{ 'id|+1':1,
        'engName|2-4':'Hello',
        'chinaName|5':'Chinese',
        'number|1-6':3,
        'aNumber|1-6.5':4,
        'first: '@FIRST',    //指随机生成英语中的first name
        middle: '@FIRST',
        last: '@LAST',      //指随机生成英语中的last name
        full: '@first @middle @last' }]  //@+变量名,指引用该变量的属性值
    })
        console.log(`data:${JSON.stringify(data, null, 4)}`)
}

生成的结果如下:

生成随机json数据

4.语法规范

4.1数据模板定义规范(Data Template Definition,DTD)

数据模板中的属性构成:“name|rule”:value

(1).属性值是字符串String

'name|min-max': string

通过重复 string 生成一个字符串,重复次数大于等于 min,小于等于 max。

'name|count': string

通过重复 string 生成一个字符串,重复次数等于 count。

'engName|2-4':'Hello',

'chinaName|5':'Chinese',

生成规则1

(2)属性值是数字Number

'name|+1': number

属性值自动加 1,初始值为 number。

'name|min-max': number

生成一个大于等于 min、小于等于 max 的整数,属性值 number 只是用来确定类型。

'name|min-max.dmin-dmax': number

生成一个浮点数,整数部分大于等于 min、小于等于 max,小数部分保留 dmin 到 dmax 位。

data = Mock.mock({
                'list|1-10':[{
                'number1|1-100.1-10': 1,
                'number2|123.1-10': 1,
                'number3|123.3': 1,
                'number4|123.10': 1.123 }]
            })  

===>生成结果:

{ "list": [ 
                { "number1": 2.73803408, "number2": 123.46, "number3": 123.748, "number4": 123.1237616335 },
                { "number1": 67.0562188234,"number2": 123.5817686348,"number3": 123.541,"number4": 123.1238281167 }]
            }

(3)属性值是布尔型Boolean

'name|1': boolean

随机生成一个布尔值,值为 true 的概率是 1/2,值为 false 的概率同样是 1/2。

'name|min-max': value

随机生成一个布尔值,值为 value 的概率是 min / (min + max),值为 !value 的概率是 max / (min + max)。

data = Mock.mock({
                'list|1-10':[{
                'boolean1|1': false,
                'boolean2|6-5': true }]
                })

===》生成结果:

data:{ "list": [ 
                { "boolean1": true, "boolean2": false }, 
                { "boolean1": true, "boolean2": true }, 
                { "boolean1": true, "boolean2": false }]
            }

(4)属性值是对象Object

'name|count': object

从属性值 object 中随机选取 count 个属性。

'name|min-max': object

从属性值 object 中随机选取 min 到 max 个属性。

const mockdata = Mock.mock({
        'people|3':{name:'Marry',age:14,gender:'girl',eat:'apple'},
        'peoples|1-2':{name:'Marry',age:14,gender:'girl',eat:'apple'}
      })

===》生成结果


image.png

5.方法

5.1Mock.mock()

rurl :可选。表示需要拦截的 URL,可以是 URL 字符串或 URL 正则。
例如: //domain/list.json/、'/domian/list.json'。

rtype:可选。表示需要拦截的 Ajax 请求类型。
例如 GET、POST、PUT、DELETE 等。

template:可选。表示数据模板,可以是对象或字符串。
例如 { 'data|1-10':[{}] }、'@EMAIL'。

function(options):可选。表示用于生成响应数据的函数。

(1)Mock.mock(template)

根据模板生成模拟数据

(2)Mock.mock( rurl, template )

记录数据模板。当拦截到匹配 rurl 的 Ajax 请求时,将根据数据模板 template 生成模拟数据,并作为响应数据返回。

(3)Mock.mock( rurl, function( options ) )

记录用于生成响应数据的函数。当拦截到匹配 rurl 的 Ajax 请求时,函数 function(options) 将被执行,并把执行结果作为响应数据返回。

(4)Mock.mock( rurl, rtype, template )

记录数据模板。当拦截到匹配 rurl 和 rtype 的 Ajax 请求时,将根据数据模板 template 生成模拟数据,并作为响应数据返回。

(5)Mock.mock( rurl, rtype, function( options ) )

记录用于生成响应数据的函数。当拦截到匹配 rurl 和 rtype 的 Ajax 请求时,函数 function(options) 将被执行,并把执行结果作为响应数据返回。

5.2 Mock.setup()

配置拦截 Ajax 请求时的行为。支持的配置项有:timeout。

5.3 Mock.Random()

是一个工具类,用于生成各种随机数据。(在数据模板中成为占位符,书写格式为@占位符(参数 [, 参数]))

5.4 Mock.valid()

校验真实数据 data 是否与数据模板 template 匹配。

5.5 Mock.toJSONSchema()

把 Mock.js 风格的数据模板 template 转换成JSON Schema

二、在polymer项目中

前言:因为在polymer中,js文件不能直接引用外部文件,所以我们需要新建一个html,把我们需要引用的文件放在HTML中使用。

1.安装mockjs

npm install -g bower
bower install --save mockjs

2.在项目中新建mockData文件夹

mockData文件夹

3.mockData.js中定义模拟数据以及需要拦截的接口

(function () {
  const userInfo = Mock.mock({
    "rows|10":[{ //"name|number":[]生成number个数组
      "id|+1":1, //"name|+number":number 生成的每个id比前面一个大number
      "name":"@name()",//"@name()"随机生成name
      "email": "@email()", //"@email"随机生成邮箱
      "groupId|35-47": 35, //"groupId|35-47"随机生成35-47中的某个整数
      "setGroupId|1": true,//"setGroupId|1"随机生成boolean值
      "setId|1": true,
      "setName|1": true,
      "setSort|1": true,
      "setUrl|1": true,
      "sort|1-10": 1,
      "url": "@url()" //"@url()"随机生成url
    }]
  })

  //定义你需要拦截的接口对应的方法,可重写拦截后返回的操作方法
  Mock.mock(RegExp(getMockUrl('/management/link/groupsList.do') + ".*"),'get',function (options) { //get请求使用正则匹配是为了拦截带参数的get请求
    return userInfo
  })
  Mock.mock(getMockUrl('/management/link/add.do'),'post',function (options) {
    addMockData(options,userInfo)
  })
  Mock.mock(getMockUrl('/management/link/update.do'),'post',function (options) {
    updateMockData(options,userInfo)
  })
  Mock.mock(getMockUrl('/management/link/delete.do'),'delete',function (options) {
    deleteMockData(options,userInfo)
  })
})()
//把url统一改成'/mock'+url
function getMockUrl(url){
  return `/mock${url}`
}
//把请求的参数转换成js
function getOptions(options) {
  return JSON.parse(options.body)
}
//add method
function addMockData(options,mockData) {
  const obj = this.getOptions(options)
  obj.id = mockData.rows.length+1
  mockData.rows.push(obj)
}
//update method
function updateMockData(options,mockData) {
  const obj = this.getOptions(options)
  mockData.rows = mockData.rows.map(item=>{
    return item.id === obj.id?obj:item
  })
}
//delete method
function deleteMockData(options,mockData) {
  const id = parseInt(this.getOptions(options).id)
  mockData.rows = mockData.rows.filter(item=>{
    return item.id !== id
  })
}

4.在mockData.html中引用mockjs以及mockData.js两个脚本文件

<script src="../../../bower_components2/mockjs/dist/mock.js"></script>
<script src="./mock-data.js"></script>

5.需要使用模拟数据的页面,引用mockData.html

image

在已有的项目中加入mockjs框架,已封装http请求接口,且不影响原有的使用。

image

在该封装接口的脚本中引用mockData.html,在原来的基础上加一个参数,判断是否使用模拟数据.如果是,在url上做文章。这样可以保证不会影响到其他模块的使用。

三、在vue项目中

1.先在vue工程文件中下载mockjs

一般是:

npm install mockjs

2.在src中创建 mock.js,在mock.js中导入mockjs,即可使用Mock的各种方法

const Mock = require('mockjs')     //导入mockjs
            const userInfo =Mock.mock({       //生成随机数
                'data|10':[
                    { 'id|+1':1,
                    name:'@ctitle(2,10)',
                    avatar:'@image(\'600x600\',@color)',
                    'gender|1':true,
                    'age|18-25':20 }]
                 })
Mock.mock('/api/userInfo/queryUser','get',function () { return userInfo.data}) //获取模拟
数据的接口

3.在main.js中导入刚刚新建的mock.js

require('./mock.js')

至此,我们就可以访问我们定义的模拟数据接口了。

以下是鄙人自己写的实现数据增删改查接口:

import Mock from 'mockjs'
export default {
  mockData(){
    const userInfo = Mock.mock(
      {
        'data|10':[{
          'id|+1':1,
          name:'@ctitle(2,10)',
          avatar:'@image(\'600x600\',@color)',
          'gender|1':true,
          'age|18-25':20
        }]
      }
    )
//模拟删除数据
    Mock.mock('/api/userInfo/deleteUser','delete',function (options) {
      const id = parseInt(JSON.parse(options.body).id)
      userInfo.data = userInfo.data.filter(item=>{
        return item.id !== id
      })
      return userInfo.data
    })
//模拟查询数据
    Mock.mock('/api/web/itemPrice/findFinalPriceOfferPage','get',function (options) {
      return userInfo.data
    })
//模拟更新数据
    Mock.mock('/api/userInfo/updateUser','post',function (options) {
      const obj = JSON.parse(options.body)
      userInfo.data = userInfo.data.map(item=>{
        return item.id === obj.id?obj:item
      })
      return userInfo.data
    })
//模拟添加数据
    Mock.mock('/api/userInfo/addUser','post',function (options) {
      const obj = JSON.parse(options.body)
      obj.id = userInfo.data.length+1
      userInfo.data.push(obj)
      return userInfo.data
    })
  }
}

在vue.config.js中设置代理服务,即可以测试接口是否被拦截

devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:9094', // 请求的接口
        changeOrigin: true,
        ws: true,
        pathRewrite: {
          '^/api/': ''
        }
      }
    }
  }

在我们的实际项目中,很多时候都是把get post请求封装好,以不用多次自己手写ajax或者axios请求。所以我们可以这样做:

在封装请求的方法里加一个isMock判断是否使用模拟数据,是的话改变它的url,如:

get(url,params={},isMock){
    url = isMock?`/mock${url}`:url
    return new Promise((resolve,reject)=>{
      axios.get(url,params)
        .then(res=>{
          resolve(res)
        })
        .catch(error=>{
          reject(error)
        })
    })
  }

在mockUrl中,在url前缀加上/mock,以防止在不使用mock数据模拟的时候,影响了原有的url请求

Mock.mock(RegExp('/mock/api/web/itemPrice/findFinalPriceOfferPage' +'.*'), 'get', function () { 
                 return data.itemPriceInfo
                })

四、在vue项目中的应用(升级版)

适用对象: 项目已开发了一部分,后续想引入mockjs
优点: 不影响原来请求的使用,其他成员想使用模拟数据时只需要新建按要求data数据即可,不需要修改原有的代码,不担心错提交或漏提交导致测试环境甚至生产环境跑不起来问题
前面操作一样,先install mockjs,在封装好的http请求中,若使用模拟数据,给url加个前缀识别,如:。

get (url, params, isMock = false) {
    url = isMock ? `/mock${url}` : url
    return new Promise((resolve, reject) => {
      axios.get(url, {
        params: params
      }).then(res => {
        resolve(res.data)
      }).catch(err => {
        reject(err)
      })
    })
  }

不同的是:

在目录中,新建mockData文件夹,mockData的组成有:
data文件夹:用于存放其他成员使用模拟数据时其数据文件;
getMockData.js:自动读取data中新增的数据脚本文件;
mockBaseFunction:封装一些基础的增删改查方法,方便其他成员按需引用。

mockData目录

data中的数据文件,需要用export 封装起来,方便读取。

import mockBaseFunction from '../mockBaseFunction'
const successData = { data: null, meta: { success: true, message: 'ok' } }
const itemPriceInfo = mockBaseFunction.mock({
  data: {
    'rows|5': [{
      category: '@name()', // '@name()随机生成英文名字'
      createdByName: '@cname()', // '@name()随机生成中文名字'
      'id|+1': 63, // "id|+number":number 生成的每个id比前面一个大number
      manufacturerName: '@ctitle()',
      'status|1-3': 3, // "status1-3"随机生成1-3中的某个整数
      supplierCompanyId: 61,
      supplierCompanyName: '@ctitle()', // '@ctitle()'随机生成中文标题
    }],
    pageResponse: { start: 0, limit: 5, results: 60 }
  },
  meta: {
    message: 'ok',
    success: true
  }
})

export default {
  mockDemo () {
    // 拦截的url:fun.getMockUrl('需要拦截的url'),请求方法,可为空:'',拦截后的操作方法
    // 拦截get请求,返回模拟数据
    mockBaseFunction.mock(RegExp(mockBaseFunction.getMockUrl('/api/web/itemPrice/findFinalPriceOfferPage') + '.*'), 'get', function (options) {
      return mockBaseFunction.queryMockData(options, itemPriceInfo)
    })
    // 拦截post请求,增加数据,拦截后返回增加模拟数据方法
    mockBaseFunction.mock(mockBaseFunction.getMockUrl('/api/userInfo/addUser'), 'post', function (options) {
      mockBaseFunction.addMockData(options, itemPriceInfo, successData)
    })
    // 拦截post请求,修改数据,拦截后返回修改模拟数据方法
    mockBaseFunction.mock(mockBaseFunction.getMockUrl('/api/userInfo/updateUser'), 'post', function (options) {
      mockBaseFunction.updateMockData(options, itemPriceInfo, successData)
    })
    // 拦截post请求,删除数据,拦截后返回删除模拟数据方法
    mockBaseFunction.mock(mockBaseFunction.getMockUrl('/api/userInfo/deleteUser'), 'post', function (options) {
      mockBaseFunction.deleteMockData(options, itemPriceInfo, successData)
    })
  }
}

getMockData.js

(function () {
  const mockData = require.context('../mockData/data', false, /[A-Za-z0-9-_,\s]+\.js$/i)
  mockData.keys().reduce((modules, modulePath) => {
    // set './app.js' => 'app'
    const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
    const value = mockData(modulePath)
      modules[moduleName] = value.default
      return modules[moduleName][moduleName]()
  }, {})
})()

重点在于使用require.context()读取data中的数据文件

mockBaseFunction.js

import Mock from 'mockjs'

export default {
  mock: Mock.mock,  //这里定义mock变量,是为了方便其他成员使用mockjs,不需要再自己引用mockjs,直接引用mockBaseFunction.js即可
// 将url转换成/mock+url格式
  getMockUrl (url) {
    return `/mock${url}`
  },
// 将请求的传参转换成js对象
  getOptions (options) {
    return JSON.parse(options.body)
  },
// 查询模拟数据
  queryMockData (option, mockData, selfFunction) {
    if (typeof (selfFunction) !== 'function') {
      return mockData
    }
    return selfFunction()
  },
// 模拟新增数据
  addMockData (options, mockData, successData = {}, selfFunction) {
    const params = this.getOptions(options)
    if (typeof (selfFunction) !== 'function') {
      params.id = mockData.data.rows.length + 1
      mockData.data.rows.push(params)
      return successData || ''
    }
    return selfFunction()
  },
// 模拟编辑数据
  updateMockData (options, mockData, successData = {}, selfFunction) {
    if (typeof (selfFunction) !== 'function') {
      const obj = this.getOptions(options)
      mockData.data.rows = mockData.data.rows.map(item => {
        return item.id === obj.id ? obj : item
      })
      return successData || ''
    }
    return selfFunction()
  },
// 模拟删除数据
  deleteMockData (options, mockData, successData = {}, selfFunction) {
    if (typeof (selfFunction) !== 'function') {
      const id = parseInt(this.getOptions(options).id)
      mockData.data.rows = mockData.data.rows.filter(item => {
        return item.id !== id
      })
      return successData || ''
    }
    selfFunction()
  }
}

突破点:读取data中的数据文件并且调用封装好的方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容