微信小程序原生页面和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() {

}

参考资料

感谢阅读,欢迎评论^-^

打赏我吧^-^

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