????????首先局义,微信小程序向web-view傳遞數(shù)據(jù)一般通過(guò)地址欄傳參的形式(給src賦值或者修改hash)鳞上,這樣一般就已經(jīng)能夠滿(mǎn)足實(shí)際開(kāi)發(fā)需求了,所以這里主要探討web-view向微信小程序傳參几颜。下面笼踩,我們從官方文檔入手,基于web-view標(biāo)簽自身的能力特點(diǎn)做一些嘗試:
一谷市、JSSDK提供的wx.miniProgram.postMessage
????????文檔中說(shuō)此方法只能在“小程序后退蛔垢、組件銷(xiāo)毀、分享迫悠、復(fù)制鏈接”時(shí)才會(huì)觸發(fā)鹏漆,意思也就是說(shuō)通信不是即時(shí)的,而實(shí)際中,我們大多是需要即時(shí)通信的艺玲,所以該方法的用處有限括蝠。
// h5頁(yè)面
wx.miniProgram.postMessage({data: 'foo' })
wx.miniProgram.postMessage({data: {foo: 'bar'} })
// 小程序
<web-view src="{{url}}" bindmessage="messageHandler"></web-view>
二、路由跳轉(zhuǎn)(wx.miniProgram.navigateTo/redirectTo等)
????????文檔提供了一些web-view改變小程序路由的方法饭聚,那么能否通過(guò)這些方法傳遞數(shù)據(jù)忌警,然后在小程序中攔截路由,拿到數(shù)據(jù)后再阻止跳轉(zhuǎn)秒梳?答案是不行法绵。原因是:小程序雖然可以通過(guò)wx.onAppRoute監(jiān)聽(tīng)路由變更,但不能阻止路由跳轉(zhuǎn)行為酪碘。
????????另外礼烈,即便是當(dāng)前頁(yè)面跳轉(zhuǎn)到當(dāng)前頁(yè)面也不行(即/page/webview/index跳轉(zhuǎn)到/page/webview/index?a=123),頁(yè)面會(huì)重新加載婆跑,閃現(xiàn)白屏此熬。
三、事件綁定bindload
????????web-view標(biāo)簽提供了3個(gè)事件:bindload滑进、bindmessage犀忱、binderror。其中扶关,bindmessage是配合上面的postMessage使用的阴汇;binderror是網(wǎng)頁(yè)加載失敗時(shí)觸發(fā)的;只有bindload(頁(yè)面加載成功時(shí)觸發(fā))存在可利用的契機(jī)节槐。
? ??????3.1 在h5頁(yè)面中修改location.href搀庶,通過(guò)地址欄向小程序傳參
????????這是最直接能想到的辦法,H5頁(yè)面不復(fù)雜的話(huà)铜异,用戶(hù)幾乎感覺(jué)不到頁(yè)面重新加載帶來(lái)的影響哥倔。不過(guò),該方式隱性要求我們:在開(kāi)發(fā)時(shí)揍庄,最好將H5頁(yè)面設(shè)計(jì)成“頁(yè)面的所有狀態(tài)都使用地址欄參數(shù)和localStorage來(lái)維護(hù)”咆蒿,這樣,無(wú)論是“小程序變更h5頁(yè)面”還是“h5頁(yè)面向小程序傳遞自身當(dāng)前的狀態(tài)”都會(huì)很方便蚂子。
? ??????3.2 是否可以模擬觸發(fā)load事件來(lái)優(yōu)化上述方式(fail)
????????答案是不行的沃测。假如是在h5頁(yè)面內(nèi),模擬觸發(fā)load事件是可行的食茎,但是網(wǎng)頁(yè)內(nèi)window的load并不會(huì)冒泡給web-view標(biāo)簽蒂破。
? ??????3.3 是否可以使用多標(biāo)簽來(lái)優(yōu)化上述方式(fail)
????????現(xiàn)在的瀏覽器都支持多標(biāo)簽頁(yè),那么web-view標(biāo)簽是否也可以同時(shí)打開(kāi)兩個(gè)標(biāo)簽頁(yè)(頁(yè)面a别渔、頁(yè)面b)附迷,其中頁(yè)面a用來(lái)展示頁(yè)面惧互,頁(yè)面b(假設(shè)它是頁(yè)面a用window.open(‘page-b’, ‘_blank’)打開(kāi)的)則不顯示;需要傳參時(shí)挟秤,頁(yè)面a修改頁(yè)面b的地址壹哺,繼而觸發(fā)load事件,將參數(shù)傳遞給小程序艘刚?
????????答案是不行的管宵。
????????雖然window.open方法可以執(zhí)行,但貌似在web-view中攀甚,“_blank”跟“_self”一樣箩朴,無(wú)論是頁(yè)面a操作頁(yè)面b,還是頁(yè)面b操作頁(yè)面a都操作的是同一個(gè)標(biāo)簽頁(yè)秋度。
? ??????3.4 是否可使用history.pushState/replaceState或修改hash來(lái)觸發(fā)load(fail)
????????答案是不行的炸庞。畢竟這兩種方法都只是修改地址,并不影響網(wǎng)頁(yè)內(nèi)容荚斯,而load是需要網(wǎng)頁(yè)加載才可能觸發(fā)埠居。
四、Websocket通信
????????小程序和H5網(wǎng)頁(yè)通過(guò)websocket服務(wù)器進(jìn)行通信事期,這種方式固然很好滥壕,但需要額外成本,此處不作考慮兽泣。