若是你們以爲有用,更多的模塊請點擊查看javascript
系列文章html
點擊訪問demo前端
掃碼訪問vue
爲何到了今天,還要提hybrid開發,就我所在團隊從中得到的好處有:java
JSBridge是前端和客戶端交互的核心概念,下面就分享一下咱們的經驗,由於目前android設備通常都是4.4以上系統,故咱們直接廢棄了protocol
自定義協議的交互方式,直接使用上下文方式,這點須要客戶端開發人員注意。android
下面介紹一下vue-viewplus 一個簡化Vue應用開發的工具庫中的JSBridge橋接模塊js-bridge-context.js:ios
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模塊,後期若有須要將會分享;
/** * [*] `$vp#onParseClientResp(res)` * 當客戶端返回結果以後會回調該鉤子,應用能夠經過該函數來判斷客戶端返回的消息是否正確,意思就和`util-http.js`模塊同樣,這裏的是否正確, * 是業務級別的; * return true 標識業務級別成功,不然爲失敗,這裏的判斷直接影響`$vp#fireEvent`返回的Promise是調用失敗仍是成功處理流程,若是不定義該配置項,那麼`$vp#fireEvent`將會直接返回成功 */
onParseClientResp
複製代碼
/** * 客戶端暴露給前端的全局對象名稱 * [*] {String} * <p> * 模塊安裝的時候回檢測當前運行環境中是否存在這樣一個名稱的上下文對象 */
name = 'ViewPlus'
複製代碼
/** * 標識是否啓用當前模塊 * [可選] {Boolean} * <p> * + 有一種狀況,應用但願手動設置`$vp.runNative`標識,以便程序能夠方便知道本身的運行環境,可是又不想使用當前模塊,這種狀況,就能夠單獨把這裏配置爲false * 固然若是`$vp.runNative`已經被設置爲false,那麼還須要這個模塊幹嗎呢? */
enable = runNative
複製代碼
/** * $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'))
}
}
複製代碼
/** * $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)
複製代碼
若是你們以爲有用,更多的模塊請點擊查看