用Vue來進行移動Hybrid開發和客戶端間數據傳輸的一種方法

若是你們以爲有用,更多的模塊請點擊查看javascript

點擊訪問demo前端

掃碼訪問vue

爲何到了今天,還要提hybrid開發,就我所在團隊從中得到的好處有:java

  • 團隊較小、業務較重、迭代頻繁、須要緊急響應的團隊和項目比較適合用
  • 使用單頁應用技術團隊比較適合,這一點是我在實踐了雲南農信手機銀行這樣一個企業級金融app獲得的結論,由於單頁應用若是首屏加載和頁面組件懶加載等機制作的好的話,其實通常單頁應用的加載速度不亞於普通的原生開發,針對這種金融項目,建議直接將前端項目打包以後放到web sevrer,而不是直接打包到客戶端,這樣方便維護,由於這種項目,甲方其實對頁面的渲染速度的要求仍是其次,安全和bug的修復速度纔是放在首位

JSBridge是前端和客戶端交互的核心概念,下面就分享一下咱們的經驗,由於目前android設備通常都是4.4以上系統,故咱們直接廢棄了protocol自定義協議的交互方式,直接使用上下文方式,這點須要客戶端開發人員注意。android

下面介紹一下vue-viewplus 一個簡化Vue應用開發的工具庫中的JSBridge橋接模塊js-bridge-context.jsios

js-bridge-context.js JSBridge橋接模塊,用於簡化前端和客戶端(Android && IOS)直接的交互,配合Jiiiiiin/android-viewplus 一個安卓混合客戶端開發庫可讓hybrid開發易如反掌 :)git

這個模塊須要和客戶端配合使用,有如下一些約束和條件:程序員

  • 客戶端只須要暴露一個上下文對象、一個接口,由於模塊再調用客戶端時候會約定一個數據傳輸對象,來知足客戶端的內容分發,如: android那邊多是這樣的:
mWebView.addJavascriptInterface(new Object(){
    @JavascriptInterface
    public String event(String params) {
        final JSONObject jsonObj = JSONObject.parseObject(params);
        String event = jsonObj.getString("event");
        String action = jsonObj.getString("action");
        String callback = jsonObj.getString("callback");
        String listener = jsonObj.getString("listener");
        JSONObject rparams = jsonObj.getJSONObject("params");
        switch (action) {
            case "toast":
                ToastUtils.showLong(rparams.getString("msg"));
                // 模擬異步執行其餘事情
                new Thread(() -> {
                    // 異步通知前端,即java調用前端js
                    HANDLER.post(() -> mWebView.evaluateJavascript(listener + "('" + params + "');", null));
                }).start();
                // 同步返回標識請求成功或失敗
                HANDLER.post(() -> mWebView.evaluateJavascript(callback + "('seccuess');", null));
                break;
            default:
        }
        return params;
    }
}, "ViewPlus");
複製代碼

上面簡單來講就是,安卓客戶端向瀏覽器暴露了一個window.ViewPlus#event(command),這樣一個接口,而後經過解析command這個字符串類型的json對象,來判斷前端但願客戶端作什麼,作完以後怎麼處理;github

那麼當前模塊就是爲了簡化和客戶端的交互,讓每一次請求,就行完成一個ajax操做同樣,如:

this.$vp.fireEvent({
  event: 'UIEvent',
  action: 'toast',
  params: {
    msg: 'hello world'
  }
}).then(res => {
  console.log('請求成功,客戶端返回的同步請求結果', res)
}).catch(err => {
  console.log('請求出錯,客戶端返回的同步錯誤信息', res)
})
複製代碼

使用模塊提供的$vp.fireEvent方法,咱們只須要經過傳遞一條command指令就能夠獲得一個{Promise},這裏和util-http.js模塊的請求方法同樣; command的含義:

{
  // [*] event用來標識請求那個客戶端的模塊,方便客戶端根據業務組織「內部JSBridge接口」
  event: 'UIEvent',
  // action標識請求對應模塊的那個方法或者說交易,客戶端據此去調用該方法
  action: 'toast',
  // 【可選】params用來傳遞對應action須要的參數
  params: {
    msg: 'hello world'
  }
  // 【可選】listener用來告訴客戶端執行完(通常而言是異步操做)方法只會須要回調該方法通知前端
  listener: ([客戶端傳遞]) => {}
}
複製代碼

至於同步消息的處理,由於ios和android的處理不一樣,插件已經幫你磨平了,客戶端程序員須要注意的是command中針對ios必定會有一個callback參數, 標識action方法處理完成須要「立刻」調用反饋給前端,當前請求是否處理完成,而android則沒有這個參數,是由於public String event(String params) 這個暴露的接口的返回值,就完成了這個需求;

還須要客戶端程序員注意的是: ios,模塊調用的是global.webkit.messageHandlers[name].postMessage(JSON.stringify(command))來調用,這裏的name是當前模塊的context.name配置項; android,模塊調用的是global[name].event(JSON.stringify(command)),這裏的event是寫死的!!!

因此這裏推薦一個安卓類庫,專門爲當前插件而訂製,幫你們完成了這一系列工做:android-viewplus一個安卓混合客戶端開發庫

哈哈哈,強行安利一波;

示例

模擬前端調用客戶端toast打印一個'hello vplus'

瀏覽線上示例

<template>
  <div id="JsBridgeContext">

    <group title="使用$vp#fireEvent請求客戶端彈出一個toast:" label-width="15em" class="bottom-group">
      <box gap="10px 10px">
        <x-button mini plain @click.native="doFireEvent" class="fl-right">運行</x-button>
      </box>
    </group>

  </div>
</template>

<script type="text/ecmascript-6"> import demoMixin from './demo-mixin' export default { mixins: [demoMixin], methods: { doFireEvent() { try { this.$vp.fireEvent({ event: 'UIEvent', action: 'toast', params: { msg: 'hello vplus' } }).then(res => { this.$vp.uiDialog(res, { title: '橋接調用成功', showCode: true }) }).catch(err => { this.$vp.uiDialog(`橋接調用失敗 ${err.message}`) }) } catch (e) { this.$vp.uiDialog(`橋接調用失敗 ${e.message}`) } } } } </script>
複製代碼

除了上面這種直白的交互,咱們針對客戶端數據傳輸安全和前端跨域問題,也依賴當前模塊集成了一個經過客戶端代理前端發送請求的util-http.js模塊,後期若有須要將會分享;

配置

onParseClientResp[*]

/** * [*] `$vp#onParseClientResp(res)` * 當客戶端返回結果以後會回調該鉤子,應用能夠經過該函數來判斷客戶端返回的消息是否正確,意思就和`util-http.js`模塊同樣,這裏的是否正確, * 是業務級別的; * return true 標識業務級別成功,不然爲失敗,這裏的判斷直接影響`$vp#fireEvent`返回的Promise是調用失敗仍是成功處理流程,若是不定義該配置項,那麼`$vp#fireEvent`將會直接返回成功 */
    onParseClientResp
複製代碼

name[*]

/** * 客戶端暴露給前端的全局對象名稱 * [*] {String} * <p> * 模塊安裝的時候回檢測當前運行環境中是否存在這樣一個名稱的上下文對象 */
    name = 'ViewPlus'
複製代碼

enable

/** * 標識是否啓用當前模塊 * [可選] {Boolean} * <p> * + 有一種狀況,應用但願手動設置`$vp.runNative`標識,以便程序能夠方便知道本身的運行環境,可是又不想使用當前模塊,這種狀況,就能夠單獨把這裏配置爲false * 固然若是`$vp.runNative`已經被設置爲false,那麼還須要這個模塊幹嗎呢? */
    enable = runNative
複製代碼

API接口

onParseClientResp

/** * $vp.onParseClientResp() * 方便應用調用該方法判斷`command#listener`的返回結果,直接代理到`js-bridge-context`配置項`onParseClientResp` * @returns {Boolean} true 標識業務級別成功,不然爲失敗 */
  onParseClientResp() {
    if (_.isFunction(_onParseClientResp)) {
      return this::_onParseClientResp()
    } else {
      emitErr(new Error('on_parse_client_resp_func_not_config'))
    }
  }
複製代碼

fireEvent

/** * $vp.fireEvent(command = null) * 應用能夠直接調用該方法完成和客戶端的交互 * <p> * 協議方式請求客戶端 * command的格式: * const command = { * // [*] event用來標識請求那個客戶端的模塊,方便客戶端根據業務組織「內部JSBridge接口」 * event: 'UIEvent', * // action標識請求對應模塊的那個方法或者說交易,客戶端據此去調用該方法 * action: 'toast', * // 【可選】params用來傳遞對應action須要的參數 * params: { * // 自定義參數 * msg: 'hello world' * } * // 【可選】listener用來告訴客戶端執行完(通常而言是異步操做)方法只會須要回調該方法通知前端 * listener: ([客戶端傳遞]) => {} * } * <p> * @param {Object} [command=null] 客戶端所需的調用消息 */
  fireEvent(command = null)
複製代碼

若是你們以爲有用,更多的模塊請點擊查看

相關文章
相關標籤/搜索