首頁 > 軟體

JS技巧多狀態頁面中的mock方案詳解

2023-01-14 14:00:03

引言

我們有時候會遇到一個業務頁面存在很多個狀態,甚至子狀態,比如訂單詳情就是其中的典型,涉及從訂單建立到訂單結束,以及售後等流程。維護起來每個狀態對應一份資料,雖然我們 QA 提供了資料構造平臺,但構造一份對應狀態的資料還是需要花費不少時間,而且序列流程一旦出錯的話只能重新來一遍。

後期維護階段也不容易構造對應狀態的資料,導致排查頁面問題比較耗時。

另外一個問題就是從頭熟悉業務的話成本比較高,如果有一個直觀的頁面能夠看到頁面樣式會好很多。

以上就是設計一個多狀態 mock 工具初衷,讓開發者在頁面中直接選擇對應狀態,就可以切換到對應頁面。

技術選型

目前轉轉 app 測試包,webview 頁面氣泡浮層已經有兩個了——使用者端工具和 eruda,再多就亂套了,所以最好整合在現有的工具基礎上。使用者端部分功能我們接觸不到也不瞭解,在現有條件下只有 eruda 可用。

Eruda 是一個很強大的前端頁面偵錯工具庫,我們使用者端 webview 也內建了,在測試包中可以很方便的藉助 eruda 偵錯頁面,觀察紀錄檔。同時 eruda 也支援外掛,通過外掛來擴充套件 eruda 的功能。 我們的工具就基於 eruda 外掛來實現。

實現效果預覽:

總體流程如下:

整個流程大概三個部分組成

  • 業務邏輯改造
  • Eruda 外掛
  • mock 資料整理

業務邏輯改造

首先要實現這樣一個方案核心依賴於業務使用的請求庫,以及是否能夠對請求庫進行修改。

我們業務使用的基於 axios 的請求庫,其暴露了實際傳送請求的 adapter 邏輯,我們可以基於 adapter 來實現介面方法的攔截。

axios adapter

藉助 axios-mock-adapter[1],可以很方便的實現我們的需求。

import { axiosInstance } from '@zz/fetch';
import MockAdapter from 'axios-mock-adapter';
export const mock = new MockAdapter(axiosInstance)
try {
  // 藉助 localstorage 實現 eruda 外掛和 axios-mock-adapter 通訊
  const mockReqConf = JSON.parse(localStorage.getItem('_mock_req'))
  if (mockReqConf && mockReqConf.mockId) {
    mock.onGet(api.getOrderDetail).reply(config => {
      // console.log('mock api', api.getOrderDetail)
      return axiosInstance.get('https://mockrepository.zhuanzhuan.com/orderdetail?mockId=' + mockReqConf.mockId)
    })
  }
  mock.onAny()
    .passThrough()
  const isProduction = process.env.NODE_ENV === 'production'
  if (isProduction || (mockReqConf && mockReqConf.mockId === '')) {
    // sessionStorage 實現開關,如果沒有此設定,就重置設定的 mock 攔截
    if (!sessionStorage.getItem('mock-adapter')) {
      mock.restore()
    }
  }
} catch (error) {
  console.log('mock adapter config error', error)
}

Eruda 外掛

外掛的目的是實現兩個功能,一個是總開關,另一個是 mock 資料的展示和切換。

總開關藉助 sessionStorage,webview 關閉 sessionStorage 資料清除,這樣避免了一進入頁面就是mock資料,防止忘記關閉以及頻繁操作,需要的時候才開啟。

Mock 資料的展示設定在一個組態檔中,公司有統一的設定中心,基於攜程 Apollo 實現。這個檔案的作用是對映對應的狀態和 mock 資料來源,來源是統一的,所以只用引數區分即可。

範例如下:

[
  {
    "id": "/order/detail",
    "list": [
      {
        "title": "正向流程",
        "list": [
          {
            "title": "下單待發貨",
            "id": "1-0-1"
          },
          {
            "title": "寄賣下單",
            "id": "1-1-0"
          },
          {
            "title": "發貨運輸中",
            "id": "1-2-0"
          },
          {
            "title": "平臺質檢",
            "id": "1-3-0"
          }
        ]
      },
      {
        "title": "逆向流程",
        "list": [
          {
            "title": "申請退回-退回中",
            "id": "2-3-2"
          }
        ]
      }
    ]
  }
]

id 用於標識當前頁面連結,是否有設定mock資料,所以也支援設定多個頁面。

Eruda 外掛的實現參考 eruda 官方檔案。

Eruda 如何寫外掛[2] github.com/liriliri/er…

Eruda 工具庫[3] licia.liriliri.io/docs_cn.htm…

Eruda 外掛寫法類比較像一個小的模板庫,eruda 提供了外掛模板,繫結事件方式類似於 jQuery 語法,eruda 提供的 licia 工具庫均有對應方法,參考即可。

(function(root, factory) {
    if (typeof define === 'function' && define.amd) {
        define([], factory);
    } else if (typeof module === 'object' && module.exports) {
        module.exports = factory();
    } else {
        root.erudaPlugin = factory();
    }
})(this, function() {
    return function(eruda) {
        var Tool = eruda.Tool,
            util = eruda.util;
        var Plugin = Tool.extend({
            name: 'plugin',
            init: function($el) {
                this.callSuper(Tool, 'init', arguments);
                this._style = util.evalCss(
                    [
                        '.eruda-dev-tools .eruda-tools .eruda-plugin {padding: 10px;}',
                        '.eruda-tip {padding: 10px; background: #fff; color: #263238;}'
                    ].join('.eruda-dev-tools .eruda-tools .eruda-plugin ')
                );
                $el.html(
                    '<div class="eruda-tip">Put whatever you want here:)</div>'
                );
            },
            show: function() {
                this.callSuper(Tool, 'show', arguments);
            },
            hide: function() {
                this.callSuper(Tool, 'hide', arguments);
            },
            destroy: function() {
                this.callSuper(Tool, 'destroy', arguments);
                util.evalCss.remove(this._style);
            }
        });
        return new Plugin();
    };
});

Mock 資料整理

這一部分其實是比較耗費體力的工作。需要整理每一個狀態的資料,儲存起來。前面提到公司提供的一個介面平臺,基於去哪兒 YAPI 搭建,其提供了每個介面 mock 能力,我們新增 mock 資料即可。 前面組態檔中每一個狀態下的id其實就是 mock 資料的引數。

使用的時候,點選每一個狀態,將狀態值寫入 localStorage 當中,重新整理頁面。axios 請求時檢測是否有 localStorage 設定,有的話取出對應值,拼接到 YAPI mock 介面請求當中,獲取到 mock 資料,然後頁面就是 mock 資料渲染出來的了。

初步嘗試後,可以讓我們在頁面開發過程中可以很方便得檢視不同頁面下的頁面展現,相比於之前的要麼是查詢線上資料,要麼是通過資料構造一步一步找到對應狀態,都大大節省了時間,提升了效率。

同時對於產品和設計同學,也可以快速的找對對應頁面的樣子,方便產品對現有頁面進行調整,設計同學對頁面還原度進行檢查等等。

不足之處也有,就是資料的維護,現在每一個狀態下儲存的都是一份完整的資料,如果某一部分調整了的話,那麼所有的資料都要修改,資料越多,維護成本相對來說也越高。

以上是基於現有基礎能力搭建出來的一個簡單工具,當然還有更多改進空間,請多指教。

參考資料

[1] axios-mock-adapter: github.com/ctimmerm/ax…

[2] Eruda 如何寫外掛: github.com/liriliri/er…

[3] Eruda 工具庫: licia.liriliri.io/docs_cn.htm…

以上就是JS技巧多狀態頁面中的mock方案詳解的詳細內容,更多關於JS 多狀態頁面mock的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com