mock的官网文档javascript
mock官网html
关于mockjs的优势,官网这样描述它:
1)能够先后端分离。
2)增长单元测试的真实性(经过随机数据,模拟各类场景)。
3)开发无侵入(不须要修改既有代码,就能够拦截 Ajax 请求,返回模拟的响应数据。)
4)用法简单。
5)数据类型丰富(支持生成随机的文本、数字、布尔值、日期、邮箱、连接、图片、颜色等)。
6)方便扩展(支持支持扩展更多数据类型,支持自定义函数和正则。)前端
总之:在开发中并不依赖后端的接口,咱们本身根据接口文档,在真实的请求上拦截ajax后,且根据mock的数据规则,使用mock随机生成和真实相似结构的数据。这样咱们就能够使用这些数据来调式对应的接口。编写咱们前端业务逻辑代码。vue
在学习以前,咱们项目的目录结构以下:java
### 目录结构以下: demo1 # 工程名 | |--- dist # 打包后生成的目录文件 | |--- node_modules # 全部的依赖包 | |--- app | | |---index | | | |-- views # 存放全部vue页面文件 | | | | |-- parent.vue # 父组件 | | | | |-- child.vue # 子组件 | | | | |-- index.vue | | | |-- components # 存放vue公用的组件 | | | |-- js # 存放js文件的 | | | |-- store # store仓库 | | | | |--- actions.js | | | | |--- mutations.js | | | | |--- state.js | | | | |--- mutations-types.js | | | | |--- index.js | | | |-- app.js # vue入口配置文件 | | | |-- router.js # 路由配置文件 | |--- views | | |-- index.html # html文件 | |--- webpack.config.js # webpack配置文件 | |--- .gitignore | |--- README.md | |--- package.json | |--- .babelrc # babel转码文件
一:mock安装和使用
进入项目的根目录下,执行mock安装命令以下:node
npm i -D mockjs
使用:
1. 好比生成列表数据,基本代码(在vue中演示)webpack
<template> <div> </div> </template> <script type="text/javascript"> import Mock from 'mockjs'; export default { data() { return { } }, created() { }, methods: { }, mounted() { const d = Mock.mock({ /* 属性 list 的值是一个数组,其中含有 1 到 10 个元素, 属性 id 是一个自增数(key),起始值为 1,每次增 1 数组里面的数量是随机的,1-10个中随机生成几个 */ 'list|1-10': [ { 'id|+1': 1 } ] }); // "list": [{ "id": 1 }, { "id": 2 }] console.log(d); } } </script>
具体的mock数据含义对应的文档,能够看这个对应的API文档。这里就不讲解基本语法了。git
Mock 数据的语法以下:github
Mock.mock(rurl?, rtype?, template|function(options))web
参数rurl: [可选],表示须要拦截的url,能够是url字符串或url正则。
参数rtype: [可选],表示须要拦截的ajax请求的类型,好比 GET、POST、PUT、DELETE、等。
参数 template: [可选],表示数据模板,能够是对象或字符串。好比:{ 'data|1-10': [{}]}, '@EMAIL'.
参数 function(options) [可选],表示用于生成响应数据的函数。
参数options 指向本次请求的ajax数据。
Mock.mock()(提供五种参数格式以及语法规范的使用)
1. Mock.mock(template),跟进数据模板生成模拟数据。 以下demo代码:
<template> <div> </div> </template> <script type="text/javascript"> import Mock from 'mockjs'; export default { data() { return { } }, created() { }, methods: { }, mounted() { var t = { 'title': 'kongzhi', /* 经过重复 a 生成一个字符串,重复次数大于等于1,小于等于10 */ 'string1|1-10': 'a', /* 经过重复b生成一个字符串,重复的次数等于3 */ 'string2|3': 'b', /* 属性值自动加1,初始值为100 */ 'number1|+1': 100, /* 生成一个大于等于1,小于等于100的整数,属性值100只用来肯定类型 */ 'number2|1-100': 100, /* 生成一个浮点数,整数部分大于等于1,小于等于100,小数部分保留1到10位 */ 'number3|1-100.1-10': 1, /* 生成一个浮点数,整数部分未123,小数部分1-10位 */ 'number4|123.1-10': 1, /* 生成一个浮点数,整数部分为123,小数部分3位 */ 'number5|123.3': 1, /* 生成一个浮点数,整数部分未123,小数部分为 10位 */ 'number6|123.10': 1.123, /* 随机生成一个布尔值,值为true的几率为1/2, 值为false的几率是 1/2 */ 'boolean1|1': true, /* 随机生成一个布尔值,值为true的几率是 1/(1+2), 值为false的几率是 2/(1+2) */ 'boolean2|1-2': true, /* 生成一个新对象,对象里面的属性最小是2位,最大是4位 */ 'object1|2-4': { '110000': '北京市', '120000': '天津市', '130000': '河北省', '140000': '山西省' }, /* 生成一个新对象,对象里面的属性是2位 */ 'object2|2': { '310000': '上海市', '320000': '江苏省', '330000': '浙江省', '340000': '安微省' }, /* 从属性值 ['AMD', 'CMD', 'UMD'] 中随机选取1个元素,最为最终值 */ 'array1|1': ['AMD', 'CMD', 'UMD'], /* 经过重复属性值 Mock.js生成一个新数组,重复的次数大于等于1,小于等于10 */ 'array2|1-10': ['Mock.js'], /* 经过重复属性值 Mock.js, 生成一个新数组,重复的次数为3 */ 'array3|3': ['Mock.js'], /* 执行函数 function(){}, 该函数返回值做为最终的属性值 */ 'function': function() { return this.title } }; var d = Mock.mock(t); console.log(d); } } </script>
输出结果以下所示:
2. Mock.mock(rurl, template)
记录数据模板,当拦截到匹配 rurl的ajax请求时,将根据数据模板 template生成模拟数据,并做为响应数据返回。
以下demo代码:
<template> <div> </div> </template> <script type="text/javascript"> import Mock from 'mockjs'; import { mapActions } from 'vuex'; export default { data() { return { } }, created() { this.testMock(); }, methods: { testMock() { Mock.mock('//xxx.abc.com/xxxx/yyy', { 'code': 0, 'list|1-10': [{ 'id|+1': 1, 'email': '@EMAIL' }] }); // 请求的地址是 '//xxx.abc.com/xxxx/yyy' Promise.all([this.commonActionGet(['getPower', {}])]).then((res) => { console.log(res); }); }, ...mapActions(['commonActionGet', 'commonActionGetJSON', 'commonActionPost', 'commonActionPostJSON']) }, mounted() { } } </script>
如上请求后,打印出 console.log(res); 后,打印出以下图所示:
3. Mock.mock(rurl, function(options))
记录用于生成响应数据的函数,当拦截匹配到 rurl的Ajax请求时,函数 function(options)将被执行,并把执行结果做为响应数据返回。
以下代码演示:
<template> <div> </div> </template> <script type="text/javascript"> import Mock from 'mockjs'; import { mapActions } from 'vuex'; export default { data() { return { } }, created() { this.testMock(); }, methods: { testMock() { Mock.mock('//xxx.abc.com/xxxx/yyy', function(options){ return options; }); // 请求的地址是 '//xxx.abc.com/xxxx/yyy' Promise.all([this.commonActionGet(['getPower', {}])]).then((res) => { console.log(res); }); }, ...mapActions(['commonActionGet', 'commonActionGetJSON', 'commonActionPost', 'commonActionPostJSON']) }, mounted() { } } </script>
打印 console.log(res) 结果以下:
4. Mock.mock(rurl, rtype, template)
记录数据模板,当拦截到匹配 rurl和rtype的ajax请求时,将根据数据模板template生成模拟数据,并做为响应数据返回。
以下代码演示:
<template> <div> </div> </template> <script type="text/javascript"> import Mock from 'mockjs'; import { mapActions } from 'vuex'; export default { data() { return { } }, created() { this.testMock(); }, methods: { testMock() { Mock.mock('//xxx.abc.com/xxxx/yyy', 'get', { 'list': [{ 'name': 'kongzhi' }] }); // 请求的地址是 '//xxx.abc.com/xxxx/yyy' Promise.all([this.commonActionGet(['getPower', {}])]).then((res) => { console.log(res); }); }, ...mapActions(['commonActionGet', 'commonActionGetJSON', 'commonActionPost', 'commonActionPostJSON']) }, mounted() { } } </script>
以下图所示:
5. Mock.mock(rurl, rtype, function(options))
记录用于生成响应数据的函数。当拦截到匹配 rurl 和 rtype的ajax请求时,函数 function(options) 将被执行,并把执行结果做为响应数据返回。
以下代码演示:
<template> <div> </div> </template> <script type="text/javascript"> import Mock from 'mockjs'; import { mapActions } from 'vuex'; export default { data() { return { } }, created() { this.testMock(); }, methods: { testMock() { Mock.mock('//xxx.abc.com/xxxx/yyy', 'get', function(options) { return options; }); // 请求的地址是 '//xxx.abc.com/xxxx/yyy' Promise.all([this.commonActionGet(['getPower', {}])]).then((res) => { console.log(res); }); }, ...mapActions(['commonActionGet', 'commonActionGetJSON', 'commonActionPost', 'commonActionPostJSON']) }, mounted() { } } </script>
以下图所示:
二:mock数据如何区分开发环境和正式环境?
如上代码虽然能够解决数据模拟,可是上面的代码有一个明显的缺点,就是在代码内部,若是接口正常的话,那么咱们须要把mock相关的模拟代码删除,若是是一个接口却是好,可是若是页面上有多个接口,而且一个项目对应多个单页面的话,那么这种重复的工做就显示很是麻烦,而且很不友好。
所以我这边想这样处理,在 app/index/ 下新建一个文件夹叫json文件夹,而后json文件夹里面放全部模拟相关的json文件,那么json文件的命名如何命名呢?好比一个pageA页面有多个接口获取数据,那么若是我直接以接口的名称命名的话,那么过了一段时间后,我打开json文件,一眼看过去也分不清哪一个json接口数据是那个页面的,所以我这边想这样约定下 json文件名称命名规范:页面模块名_接口名称.json, 好比我vue页面叫pageA页面,而后pageA页面有好多接口,好比其中一个接口是获取产品名称接口,假如接口名称叫 getProdName, 那么我想json命名就叫 pageA_getProdName.json. 这样的话,若是之后有多个json的话,一眼就能够看出是那个页面的接口,而且该接口的做用是干什么用的。
app/index/json/parent_yyyy.json 这样定义,在parent页面内部,有个接口名称叫 yyyy, 所以json文件
命名就叫 parent_yyyy.json; 假如接口返回的json数据以下:
{ "data": [{ "assignerId": 55, "assignerName": "仲宣", "auditStatus": 20, "auditTime": "2018-05-08 16:56:02", "borrowerIdCard": "130204199812050027", "borrowerName": "张小红", "borrowerSign": "电信白名单用户", "id": 1, "loanAmount": 3500, "loanPeriod": "12", "loanRate": 21.5, "loanTime": "2018-05-07 19:27:17", "loanUsage": "购物消费", "occurDate": 20180507, "orderId": "20180507175020345000034567893", "processInstanceId": 302, "taskId": 326, "prodName": "有借有还", "taskName": "人工审核", "userId": "68" }], "page": { "curPage": 1, "pageSize": 15 }, "query": { "assignerId": 55, "egtCreateTime": "2018-04-25 10:10:45", "isAssigned": 0 }, "code": 0, "message": "查询成功" }
如今项目的目录结构变成以下了:
### 目录结构以下: demo1 # 工程名 | |--- dist # 打包后生成的目录文件 | |--- node_modules # 全部的依赖包 | |--- app | | |---index | | | |-- views # 存放全部vue页面文件 | | | | |-- parent.vue # 父组件 | | | | |-- child.vue # 子组件 | | | | |-- index.vue | | | |-- components # 存放vue公用的组件 | | | |-- js # 存放js文件的 | | | |-- json # 存放全部json模拟数据的文件 | | | | |-- parent_yyyy.json # json文件 | | | |-- store # store仓库 | | | | |--- actions.js | | | | |--- mutations.js | | | | |--- state.js | | | | |--- mutations-types.js | | | | |--- index.js | | | |-- app.js # vue入口配置文件 | | | |-- router.js # 路由配置文件 | |--- views | | |-- index.html # html文件 | |--- webpack.config.js # webpack配置文件 | |--- .gitignore | |--- README.md | |--- package.json | |--- .babelrc # babel转码文件
那么我这边就不使用mock数据随机生成了,直接把接口文档对应的数据格式贴到我对应json文件内部,而后在页面
模拟的时候,须要配置下;
1. 首先须要安装 cross-env 插件, 该插件的具体用途请看 (https://www.cnblogs.com/tugenhua0707/p/9780621.html) , 安装命令以下:
npm install --save cross-env
2. 在package.json 文件中配置, 以下代码:
"scripts": { "dev": "cross-env NODE_ENV=development webpack-dev-server --progress --colors --devtool cheap-module-eval-source-map --hot --inline", "build": "cross-env NODE_ENV=production webpack --progress --colors --devtool cheap-module-source-map", "build:dll": "webpack --config webpack.dll.config.js", "start": "webpack-dev-server --progress --colors --devtool cheap-module-eval-source-map --hot --inline", "mock": "cross-env NODE_ENV=mock npm run start" },
如上命名配置,当咱们使用 npm run mock 的话,那么就执行mock数据,当咱们运行 npm run dev 的话,就是不mock数据,使用开发环境正式接口数据,当咱们npm run build 的话,就是线上正式打包。
3. 在webpack中如何配置呢?
module.exports = { plugins: [ // 设置环境变量信息 new webpack.DefinePlugin({ PRODUCTION: JSON.stringify(true), VERSION: JSON.stringify('5fa3b9'), BROWSER_SUPPORTS_HTML5: true, TWO: '1+1', 'typeof window': JSON.stringify('object'), 'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV) } }) ] }
4. 在vue页面中如何使用呢?
<template> <div> </div> </template> <script type="text/javascript"> import { mapActions } from 'vuex'; export default { data() { return { } }, created() { this.testMock(); }, methods: { testMock() { console.log(process.env.NODE_ENV); if (process.env.NODE_ENV === 'mock') { const Mock = require('mockjs'); const json = require('../json/parent_yyyy.json'); Mock.mock('//xxx.abc.com/xxxx/yyy', 'get', { 'list': json }); } // 请求的地址是 '//xxx.abc.com/xxxx/yyy' Promise.all([this.commonActionGet(['getPower', {}])]).then((res) => { console.log(res); let rets; if (process.env.NODE_ENV === 'mock') { rets = res[0].list; } else { rets = res; } console.log(rets); }); }, ...mapActions(['commonActionGet', 'commonActionGetJSON', 'commonActionPost', 'commonActionPostJSON']) }, mounted() { } } </script>
打印以下图所示:
能够看到设置环境为 mock了,而且模拟出了咱们想要的数据,如今咱们继续 npm run dev 后,再来看看控制台就会看到不会使用mock数据了,而直接访问接口,以下图所示:
如上看到控制台输出的是 developmemt 开发环境了。
同理,正式环境执行 npm run build 后打包,看到js文件也不会包含 mock相关的代码了。这就能够在开发环境下mock数据了,而且不须要依赖开发的接口,直接根据文档的接口数据,就能够直接模拟接口返回的数据了。