前端與native交互

1.JSBridge介紹

JSBridge 簡(jiǎn)單來(lái)講,主要是 給 JavaScript 提供調(diào)用 Native 功能的接口帕翻,讓混合開發(fā)中的『前端部分』可以方便地使用地址位置、攝像頭甚至支付等 Native 功能。

既然是『簡(jiǎn)單來(lái)講』淤堵,那么 JSBridge 的用途肯定不只『調(diào)用 Native 功能』這么簡(jiǎn)單寬泛。實(shí)際上顷扩,JSBridge 就像其名稱中的『Bridge』的意義一樣拐邪,是 Native 和非 Native 之間的橋梁,它的核心是 構(gòu)建 Native 和非 Native 間消息通信的通道隘截,而且是 雙向通信的通道扎阶。

所謂雙向通信的通道:

  • JS 向 Native 發(fā)送消息 : 調(diào)用相關(guān)功能、通知 Native 當(dāng)前 JS 的相關(guān)狀態(tài)等婶芭。

  • Native 向 JS 發(fā)送消息 : 回溯調(diào)用結(jié)果东臀、消息推送、通知 JS 當(dāng)前 Native 的狀態(tài)等雕擂。

1.1 JavaScript 調(diào)用 Native

JavaScript 調(diào)用 Native 的方式啡邑,主要有兩種:注入 API 和 攔截 URL SCHEME。

1.1.1注入 API

主要原理是井赌,通過(guò) WebView 提供的接口谤逼,向 JavaScript 的 window對(duì)象中注入對(duì)象或者方法瑰剃,讓 JavaScript 調(diào)用時(shí)弛随,直接執(zhí)行相應(yīng)的 Native 代碼邏輯,達(dá)到 JavaScript 調(diào)用 Native 的目的塘娶。

JavaScript可直接通過(guò)調(diào)用window對(duì)象下的對(duì)象或者方法纹坐,調(diào)用Native的相關(guān)接口枝冀。例如,舊版的掌通家園客戶端,通過(guò)全局注冊(cè)seebaby對(duì)象果漾,js可以這么調(diào)用客戶端:window.seebaby.getUserInfo()球切,

更多示例參考:3.4 客戶端與H5交互協(xié)議(o2o新增)

1.1.2攔截 URL SCHEME

先解釋一下 URL SCHEME:URL SCHEME是一種類似于url的鏈接,是為了方便app直接互相調(diào)用設(shè)計(jì)的绒障,形式和普通的 url 近似吨凑,例如:

ztjy://eyJjYWxsIjoibG9naW4iLCJhcmdzIjp7InR5cGUiOiIwIn19(格式:

發(fā)起這樣一個(gè)網(wǎng)絡(luò)請(qǐng)求有兩種方式:

1. 通過(guò)localtion.href;

2. 通過(guò)iframe方式户辱;

通過(guò)location.href有個(gè)問題鸵钝,就是如果我們連續(xù)多次修改window.location.href的值,在Native層只能接收到最后一次請(qǐng)求庐镐,前面的請(qǐng)求都會(huì)被忽略掉恩商。

使用iframe方式,簡(jiǎn)單的封閉如下:

var url = 'ztjy://eyJjYWxsIjoibG9naW4iLCJhcmdzIjp7InR5cGUiOiIwIn19';
var iframe = document.createElement('iframe');
iframe.style.width = 0;
iframe.style.height = 0;
iframe.style.display = 'none';
iframe.src = url;
document.body.appendChild(iframe);
setTimeout(function() {
    iframe.remove();
}, 100);

攔截 URL SCHEME 的主要流程是:Web 端通過(guò)某種方式(例如 iframe.src)發(fā)送 URL Scheme 請(qǐng)求必逆,之后 Native 攔截到請(qǐng)求并根據(jù) URL SCHEME(包括所帶的參數(shù))進(jìn)行相關(guān)操作怠堪。

在時(shí)間過(guò)程中,這種方式有一定的 缺陷:

  • 使用 iframe.src 發(fā)送 URL SCHEME 會(huì)有 url 長(zhǎng)度的隱患末患。

  • 創(chuàng)建請(qǐng)求研叫,需要一定的耗時(shí)锤窑,比注入 API 的方式調(diào)用同樣的功能璧针,耗時(shí)會(huì)較長(zhǎng)。

但是之前為什么很多方案使用這種方式呢渊啰?因?yàn)樗?支持 iOS6探橱。而現(xiàn)在的大環(huán)境下,iOS6 占比很小绘证,基本上可以忽略隧膏,所以并不推薦為了 iOS6 使用這種 并不優(yōu)雅 的方式。

1.2 Native 調(diào)用 JavaScript

相比于 JavaScript 調(diào)用 Native嚷那, Native 調(diào)用 JavaScript 較為簡(jiǎn)單胞枕,畢竟不管是 iOS 的 UIWebView 還是 WKWebView,還是 Android 的 WebView 組件魏宽,都以子組件的形式存在于 View/Activity 中腐泻,直接調(diào)用相應(yīng)的 API 即可。

Native 調(diào)用 JavaScript队询,其實(shí)就是執(zhí)行拼接 JavaScript 字符串派桩,從外部調(diào)用 JavaScript 中的方法,因此 JavaScript 的方法必須在全局的 window 上蚌斩。

以統(tǒng)計(jì)頁(yè)面停留時(shí)長(zhǎng)為例:

window.onEnter = function (startTime) {
// handler
}
window.onLeave = function (endTime) {
// handler
}

2.Dsbridge

三端易用的現(xiàn)代跨平臺(tái) Javascript bridge铆惑, 通過(guò)它,你可以在Javascript和原生之間同步或異步的調(diào)用彼此的函數(shù)。

DSBridge的設(shè)計(jì)原則就是:讓三端使用方式都是最簡(jiǎn)單的员魏!

主要特點(diǎn):

  • Android丑蛤、IOS、Javascript 三端易用撕阎,輕量且強(qiáng)大盏阶、安全且健壯。
  • 同時(shí)支持同步調(diào)用和異步調(diào)用
  • 支持以類的方式集中統(tǒng)一管理API
  • 支持API命名空間
  • 支持調(diào)試模式
  • 支持API存在性檢測(cè)
  • 支持進(jìn)度回調(diào):一次調(diào)用闻书,多次返回
  • 支持Javascript關(guān)閉頁(yè)面事件回調(diào)
  • Android端支持騰訊X5內(nèi)核

假設(shè)Native端實(shí)現(xiàn)了兩個(gè)api: testSyn名斟、testAsyn。參數(shù)以json傳遞魄眉, testSyn為同步api,執(zhí)行結(jié)束后會(huì)直接返回結(jié)果砰盐,而testAsyn為一個(gè)異步api(可能會(huì)執(zhí)行耗時(shí)操作),執(zhí)行結(jié)束后坑律,結(jié)果異步返回岩梳,同時(shí)注冊(cè)一個(gè)function,供Native端調(diào)用晃择。下面我們看看web端如何調(diào)用冀值。

//同步調(diào)用
var str=dsBridge.call("testSyn",{msg: "testSyn"});
 
//異步調(diào)用
dsBridge.call("testAsyn",{msg: "testAsyn"}, function (v) {
  alert(v);
})
 
//注冊(cè) javascript API
 dsBridge.register('addValue',function(l,r){
     return l+r;
 })

2.1JavaScript調(diào)用Native

dsBridge.call(method,[arg,callback])

同步或異步的調(diào)用Native API。

method: Native API 名稱宫屠, 可以包含命名空間列疗。

arg:傳遞給Native API 的參數(shù)。只能傳一個(gè)浪蹂,如果需要多個(gè)參數(shù)時(shí)抵栈,可以合并成一個(gè)json對(duì)象參數(shù)。

callback(String returnValue): 處理Native API的返回結(jié)果. 可選參數(shù)坤次,只有異步調(diào)用時(shí)才需要提供古劲。

2.2注冊(cè)JavaScript api供Native調(diào)用

2.2.1注冊(cè)一個(gè)普通的方法

同步
dsBridge.register(methodName|namespace,function|synApiObject)
異步
dsBridge.registerAsyn(methodName|namespace,function|asyApiObject)

dsBridge.register('addValue',function(l,r){
     return l+r;
})
dsBridge.registerAsyn('addValue',function(arg1,arg2,arg3,responseCallback){
     responseCallback(arg1+" "+arg2+" "+arg3);
})

2.2.2注冊(cè)一個(gè)對(duì)象,指定一個(gè)命名空間


//namespace test for synchronous
dsBridge.register("test",{
  tag:"test",
  test1:function(){
    return this.tag+"1"
  },
  test2:function(){
    return this.tag+"2"
  }
})
   
//namespace test1 for asynchronous calls 
dsBridge.registerAsyn("test1",{
  tag:"test1",
  test1:function(responseCallback){
    return responseCallback(this.tag+"1")
  },
  test2:function(responseCallback){
    return responseCallback(this.tag+"2")
  }
})

3.實(shí)際應(yīng)用

1.獲取命名空間(同步)
const namespace = dsbridge.call(``'getNameSpace'``)
2.獲取用戶信息

try {
    dsbridge.call(namespace + '.getUserInfo', '', val => {
        // 回調(diào)
    })
} catch (e) {}

3.跳轉(zhuǎn):jumpTo

try {
    dsbridge.call(namespace + '.jumpTo', params, val => {
        // 回調(diào)
    })
} catch (e) {}

4.注冊(cè)刷新回調(diào)方法缰猴,供客戶端調(diào)用

dsbridge.register(namespace + '.autoRefreshCallback', () => {
    // 回調(diào)
}) 
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末产艾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子滑绒,更是在濱河造成了極大的恐慌闷堡,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蹬挤,死亡現(xiàn)場(chǎng)離奇詭異缚窿,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)焰扳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門倦零,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)误续,“玉大人,你說(shuō)我怎么就攤上這事扫茅√G叮” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵葫隙,是天一觀的道長(zhǎng)栽烂。 經(jīng)常有香客問我,道長(zhǎng)恋脚,這世上最難降的妖魔是什么腺办? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮糟描,結(jié)果婚禮上怀喉,老公的妹妹穿的比我還像新娘。我一直安慰自己船响,他們只是感情好躬拢,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著见间,像睡著了一般聊闯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上米诉,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天菱蔬,我揣著相機(jī)與錄音,去河邊找鬼荒辕。 笑死汗销,一個(gè)胖子當(dāng)著我的面吹牛犹褒,可吹牛的內(nèi)容都是我干的抵窒。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼叠骑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼李皇!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起宙枷,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤掉房,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后慰丛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卓囚,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年诅病,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了哪亿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粥烁。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蝇棉,靈堂內(nèi)的尸體忽然破棺而出讨阻,到底是詐尸還是另有隱情,我是刑警寧澤篡殷,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布钝吮,位于F島的核電站,受9級(jí)特大地震影響板辽,放射性物質(zhì)發(fā)生泄漏奇瘦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一劲弦、第九天 我趴在偏房一處隱蔽的房頂上張望链患。 院中可真熱鬧,春花似錦瓶您、人聲如沸麻捻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)贸毕。三九已至,卻和暖如春夜赵,著一層夾襖步出監(jiān)牢的瞬間明棍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工寇僧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留摊腋,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓嘁傀,卻偏偏與公主長(zhǎng)得像兴蒸,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子细办,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容