• 深入浅出的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上的代码

  • 相关阅读:
    What's New in Chrome DevTools All In One
    User Timing API All In One
    Tailwind CSS All In One
    CSS 3D rotate with mouse move All In One
    Event Timing API All In One
    Long Tasks API All In One
    js get window custom global variables All In One
    Web 前端广告落地页性能监控系统 All In One
    Element Timing API All In One
    base64编码
  • 原文地址:https://www.cnblogs.com/tugenhua0707/p/9813122.html
Copyright © 2020-2023  润新知