前端同學(xué)在進(jìn)行混合app開發(fā)的時(shí)候,可能會(huì)需要調(diào)用原生的方法,例如相機(jī)等。這個(gè)時(shí)候就用到了JSBridge。JSBridge是連接Native(客戶端)和JavaScript前端的橋梁,通過JSBridge 兩端的代碼才可以通信。
Native 調(diào)用 JS
因?yàn)閔5網(wǎng)頁是通過原生端的webview加載的,所以原生端對當(dāng)前網(wǎng)頁擁有很高的權(quán)限:Native端可以直接在當(dāng)前webview里執(zhí)行js代碼。
// web端
function nativeCallback(data) {
console.log('data', data);
}
我們在js的執(zhí)行環(huán)境里定義了一個(gè)全局方法nativeCallback,native端可以直接執(zhí)行nativeCallback(123)方法,也就把數(shù)據(jù)傳給了js。
JS 調(diào)用 Native
scheme協(xié)議:可以簡單理解為自定義的url 形式如:[scheme:][//domain][path][?query][#fragment] 舉個(gè)栗子:jsbridge://openPage?url=https://www.baidu.com/
客戶端通過分析scheme就知道web端要調(diào)用原生的哪些方法,同時(shí)數(shù)據(jù)也通過query參數(shù)進(jìn)行了傳遞。
-
攔截console alert prompt 全局方法
alert('sslocal://openModal?text=hello')
native可以攔截webview中的這些方法,從而調(diào)用原生方法。 - 攔截url請求
function schemeJump (url) { // 通過iframe子窗口執(zhí)行URL
let iframe = document.createElement('iframe')
iframe.src = url
iframe.style.display = 'none'
document.documentElement.appendChild(iframe)
setTimeout(() => {
document.documentElement.removeChild(iframe)
}, 0)
}
schemeJump('sslocal://openModal?text=hello')
web端加載了一個(gè)iframe,請求了sslocal://openModal?text=hello, native端通過攔截url請求,從而調(diào)用原生方法。
-
API注入
Native可以給webview注入全局變量并掛載在window對象上,這樣前端js就可以通過window上全局對象方法來調(diào)用一些native的方法。
eg:native注入到webview全局對象為gidoorJS,通過全局對象gidoorJS可以調(diào)用掛載在其上的方法,來觸發(fā)調(diào)用native的方法。window.gidoorJS.onBaackPress()
JSBridge如何引用
-
由h5引入npm包
優(yōu)點(diǎn):JavaScript 端可以確定 JSBridge 的存在,直接調(diào)用即可
缺點(diǎn):如果后期 Bridge 的實(shí)現(xiàn)方式改變,雙方需要做更多的兼容,維護(hù)成本高 -
Native注入
注入方式和 Native 調(diào)用 JavaScript 類似,直接執(zhí)行橋的全部代碼。
優(yōu)點(diǎn):有利于保持 API 與 Native 的一致性
缺點(diǎn):在 Native 注入的方法和時(shí)機(jī)都受限,JS 調(diào)用 Native 之前需要先判斷 JSBridge 是否注入成功
雙向通信
前面我們介紹的幾種方法,都只能單向通信。如何進(jìn)行雙向通信呢?這時(shí)候就需要前端自己實(shí)現(xiàn)一個(gè)JS-SDK,維護(hù)js回調(diào)函數(shù)的Map。
詳情參考 jsbridge初探