深刻淺出的webpack4構建工具--webpack4+vue+vuex+mock模擬後臺數據(十九)

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數據了,而且不須要依賴開發的接口,直接根據文檔的接口數據,就能夠直接模擬接口返回的數據了。

查看github上的代碼

相關文章
相關標籤/搜索