zoukankan      html  css  js  c++  java
  • 深入浅出的webpack4构建工具--webpack4+vue+vuex+mock模拟后台数据(十九)

    mock的官网文档

    mock官网

    关于mockjs的优点,官网这样描述它:
    1)可以前后端分离。
    2)增加单元测试的真实性(通过随机数据,模拟各种场景)。
    3)开发无侵入(不需要修改既有代码,就可以拦截 Ajax 请求,返回模拟的响应数据。)
    4)用法简单。
    5)数据类型丰富(支持生成随机的文本、数字、布尔值、日期、邮箱、链接、图片、颜色等)。
    6)方便扩展(支持支持扩展更多数据类型,支持自定义函数和正则。)

    总之:在开发中并不依赖后端的接口,我们自己根据接口文档,在真实的请求上拦截ajax后,且根据mock的数据规则,使用mock随机生成和真实类似结构的数据。这样我们就可以使用这些数据来调式对应的接口。编写我们前端业务逻辑代码。

    在学习之前,我们项目的目录结构如下:

    ### 目录结构如下:
    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安装命令如下:

    npm i -D mockjs

    使用:
    1. 比如生成列表数据,基本代码(在vue中演示)

    <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文档。这里就不讲解基本语法了。

    Mock 数据的语法如下:

    Mock.mock(rurl?, rtype?, template|function(options))

    参数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数据了,并且不需要依赖开发的接口,直接根据文档的接口数据,就可以直接模拟接口返回的数据了。

    查看github上的代码

  • 相关阅读:
    vue 部署到服务器
    半小时学会 Vuex 数据共享
    Vue 第一次安装 经历 vue cli 3.0
    第一次使用视频截图 ant design
    Luckysheet
    关于导出--分页
    ADO.net很重要
    委托到底是什么? (转载)
    生成流水单号
    Ext.NET 基础学习笔记07 (GridPanel用法)
  • 原文地址:https://www.cnblogs.com/tugenhua0707/p/9813122.html
Copyright © 2011-2022 走看看