微信小程序原生頁面和webview頁面雙向通信問題彙總

最新更新時間:2019年11月01日13:42:34

《猛戳-查看我的博客地圖-總有你意想不到的驚喜》

本文記錄微信小程序開發過程中遇到的種種問題,歸納總結

概述

隨着微信生態的不斷髮展,微信小程序的地位變的重要,幾乎所有APP都會做小程序端的應用,雖然在開發過程中,開發成本比常規的網站類型的項目小,但也會遇到很多方案問題和技術瓶頸。

小程序原生頁面和webview頁面的雙向通信

//webview頁面的dom佈局
<view class='container'>  
	<web-view wx:if="{{url}}" class='webview' src="{{url}}" bindload="bindload" binderror="binderror" bindmessage="bindmessage"></web-view>
</view>

//js 文件
data: {
	url: ''
}
//webview 組件的三個原生事件
bindload(){
	console.log('webview load success')
}
binderror(){
	console.log('webview load error')
}
//網頁向小程序 postMessage 時,會在特定時機(小程序後退、組件銷燬、分享)觸發並收到消息。e.detail = { data },data是多次 postMessage 的參數組成的數組
bindmessage(e){
	console.log(e.detail.data)
}
  • 小程序原生頁面 跳轉到 webview頁面
//從A頁面跳轉到B頁面,B頁面是一個具有<web-view></web-view>組件的頁面
let params = {a:1,b:2}
wx.navigateTo({
	url: `/pages/webview/index?params=${JSON.stringify(params)}`,
})
//進入B頁面後的裝載webview數據,在B頁面的onLoad生命週期方法中設置url
onLoad(options){
	//使用從A頁面傳入的參數
	let params = JSON.parse(options.params)
	this.setData({
		url: params.url
	})
}
  • webview頁面 跳轉到 小程序原生頁面
//以react項目爲例
componentDidMount(){
	//獲取url中路由參數
	let query = this.props.history.location.search.slice(1)
}
//使用JSSDK向小程序原生頁面跳轉
enter(){
	let params = {a:1,b:2}
	wx.miniProgram.navigateTo({ url:`/pages/index/index?params=${JSON.stringify(params)}`})
}
//需要引入 JSSDK
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js" defer></script>
  • webview頁面 跳轉到 小程序原生頁面後,按左上角返回按鍵, webview頁面刷新的問題

如果不在生命週期方法中做任何操作,此時回退到webview頁面不會刷新,如果需要做刷新操作,有兩種方案:

  • 記錄路由棧
  • 不記錄路由棧
//在<web-view></web-view>頁面的onShow方法中做操作
//這種操作,web-view會記錄自己的路由棧,每setData一次,路由棧會增加一級,此時在<web-view></web-view>頁面按返回按鈕,回退的是<web-view></web-view>自己的路由棧,而不是小程序自身的路由棧
onShow(){
	this.setData({
		url: params.url
	})
}
//這種操作,web-view不會記錄自己的路由棧,先清空url,wx:if="{{url}}"會銷燬<web-view></web-view>組件,在回調中重新setData,相當於初始化<web-view></web-view>組件,<web-view></web-view>自身路由棧不會增加,此時在<web-view></web-view>頁面按返回按鈕,回退小程序自身的路由棧
onShow(){
	this.setData({
		url: ''
	},()=>{
		this.setData({
			url: params.url
		})
	})
}
  • 不記錄路由棧的方案,部分機型存在bug

實測中,在iPhone X和iPhone XS等機型搭配的iOS 12.4.1系統下,webview的url先清空後賦值的方案中在binderror中報錯如下:insertHTMLWebView:fail only one webView component

//webview頁面的dom佈局
<view class='container'>  
	<web-view wx:if="{{url}}" class='webview' src="{{url}}" bindload="bindload" binderror="binderror" bindmessage="bindmessage"></web-view>
</view>

//js 文件
data: {
	url: ''
}
//webview 組件的原生事件
binderror(e){
	console.log(e.detail.errMsg);//insertHTMLWebView:fail only one webView component
}

終極方案,解決從小程序原生頁面回退到webview中,刷新webview並不記錄webview自身路由棧的問題,方案如下:

//webview需要的url從公共數據app.globalData中讀取,減少頁面間通信的耦合度
onLoad(options){
	this.setData({
		url: app.globalData.url
	})
}
//
onShow(){
	if(this.firstEnter){
		this.firstEnter = false;
		return
	}
	wx.redirectTo({url:'index'})
}
//注意:這個方案會觸發onUnload事件,如果之前有相關的邏輯,需要做兼容處理
onUnload() {

}

參考資料

感謝閱讀,歡迎評論^-^

打賞我吧^-^

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章