送你一份微信小程序 web-view 开发踩坑大全

前言

原来小程序里的webView又这么多注意点。今日早读文章由腾讯imweb@结一投稿分享。

正文从这开始~~

对于开发者来说,如果 H5 页面能够直接嵌入到小程序那是再好不过了,而 web-view 组件正好就提供了这么个功能(个人类型与海外类型的小程序暂不支持使用)。简单来说它是一个可以用来承载网页的容器,会自动铺满整个小程序页面。 虽然这带来了很大的便利,但是也还是有很多需要注意的地方。

账号权限

如果要在小程序中使用 web-view 组件,则首先需要开发者账号不仅是该小程序的开发者而且还有网页开发权限,这需要在该小程序关联的公众号里面绑定开发者账号为开发者。不然在开发工具里面会弹窗提示没有网页开发权限。提示如下:

业务域名

如果 web-view 组件的 src 属性指向的不是关联的公众号文章,而是其他网页,则需要登录小程序管理后台(设置 -> 开发设置)中配置业务域名,如下图:

配置业务域名的时候会提示需要上传验证文件到该域名下进行验证。如果该域名下没有验证文件或验证文件错误,则 web-view 页面直接提示报错,无法正常访问。

除此之外,如果页面中有其他链接跳转到非业务域名,进行跳转的时候也会报错导致无法正常访问,如富文本内容中的链接,iframe,数据上报或支付跳转等其他非业务域名。

另外:避免在链接中带有中文字符,在 iOS 中会有打开白屏的问题,建议加一下 encodeURIComponent

登录态

小程序登录态与 web-view 页面登录态属于两套隔离的系统。所以得想办法让小程序中的登录态传入到 web-view 页面中。目前最简单也是最常用的方案是把 cookie作为 url 参数传入,然后再在 H5 中获取并设置 cookie,为了提高点难度,也可以搞点小动作。

当然更高明的办法是搭建一个中间服务,传入要跳转的 url 和 code,中间服务通过 code 得到 session,再返回 302 重定向地址。

组件层级

web-view 组件属于原生组件,所以层级很高,如果需要覆盖则需要使用 cover-view 组件。但是 cover-view 组件在开发工具上是看不到覆盖效果的,安卓默认也不能覆盖,只有 IOS 默认会覆盖。所以为了得到想要的效果,得使用一些非常手段:

对于安卓的默认不能覆盖,目前的解决方案是执行 setTimeout 延迟实现 cover-view 的显示,让 web-view 先显示,cover-view 后显示。

对于开发工具看不到,如要调试效果则可以先注释掉 web-view 组件

除此之外,封装一个组件的时候,如果需要盖住 web-view,肯定得选择 cover-view 组件。但是如果这个组件不仅应用在 web-view 页面,还应用在普通的小程序页面。 cover-view 又会引来另一个问题:弹窗浮层根本盖不住。如一些右下角的咨询按钮,既应用在小程序页面中,也应用在 web-view 页面中。所以做组件的时候可以做一个属性判断,如果是 web-view 页面则使用 cover-view,否则使用 view。

另外 cover-view 组件中的 button 组件并不是真的,而是用 cover-view 模拟出来的。所以修改样式的话,需要注意点。

web-view 页面中小程序环境判断

官网有记载在网页内可通过 window.__wxjs_environment 变量判断是否在小程序环境,并且建议在 WeixinJSBridgeReady 回调中使用,也可以使用 JSSDK (1.3.2 以上版本) 提供的 getEnv 接口。代码如下:

// web-view下的页面内

function ready() {

console.log(window.__wxjs_environment === 'miniprogram') // true

}

if (!window.WeixinJSBridge || !WeixinJSBridge.invoke) {

document.addEventListener('WeixinJSBridgeReady', ready, false)

} else {

ready()

}

// 或者

wx.miniProgram.getEnv(function(res) {

console.log(res.miniprogram) // true

})

实际情况,一般都会直接用 window.__wxjs_environment。但是如果页面没有加载完,它是不准的,而且如果是 web-view 中进入到第二个页面,安卓也拿不到该值,总之就一个字”很不靠谱”。

既然“不靠谱”,那就有了通过 URL 里面加参数来判断,这是铁定的稳。如添加一个 mp 参数(https://m.ke.qq.com/course/xxx?mp=1)。但是如果页面有几个跳转,总不能每个都去判断下加上 mp 参数吧。所以建议在进入的第一个页面直接种下 storage,往后的根据 storage 来判断就好了。

通过这三层保证(变量 || mp 参数 || storage),只要一个为真,则为小程序环境。这样锁定小程序环境很稳。

另外:从微信 7.0.0 开始,可以通过判断 userAgent 中包含 miniProgram 字样来判断小程序 web-view 环境。

使用 web-view 的话,请保证网页中的微信 JSSDK 的版本大于 1.3.2 ,目前微信 JSSDK 的版本为 1.4.0,其升级了分享接口。所以如果要升级微信 JSSDK 到最新版本,请记得要升级 H5 页面的分享接口。原有的 wx.onMenuShareTimeline、wx.onMenuShareAppMessage、wx.onMenuShareQQ、wx.onMenuShareQZone 接口,即将废弃,取而代之的是 updateAppMessageShareData、updateTimelineShareData。最后新接口是拿不到分享成功失败的信息的。

web-view 页面向小程序通信

目前 web-view 网页可通过 postMessage 向小程序发送信息,但是该信息只会在特定时机(小程序后退、组件销毁、分享)触发并收到消息。

小程序中通过在 web-view 中设置 bindMessage 属性,收到信息,如下图:

这对于 H5 分享转小程序分享来说提供了一个非常靠谱的方案。如有些场景会引导用户去分享(砍价、助力等),这样点击按钮出现引导的时候,就得把原先 H5 页面的分享信息传向小程序。在小程序点击分享的时候就会拿到 H5 页面传入的信息,再用这些信息构造分享即可。web-view 页面中包括 iframe首先 iframe 的域名得为业务域名,不然页面也会提示报错,无法正常显示。其次 iframe 的页面里面不能使用官网上所记载的相关接口1如果要在 iframe 中跳到其他小程序页面的话,安卓可以使用window.top.window.wx.miniProgram.xxxAPI,而 IOS 中 window.top 是行不通的。页面刷新要刷新页面,得更新 web-view 的 src 属性,即更新页面的 URL,最简单的方法就是加个时间戳参数。如详细页报名,报名成功回来就需要更新详细页报名信息。由于页面返回触发的是生命周期中的 onShow,所以需要在该函数中更新 URL 值。除此之外,如果 H5 页面中有一些播放任务(音乐,视频等),在页面进入后台的时候即 onHide 时候,应该需要把 URL 设置为空,不然音视频会在后台一直播放直至该小程序销毁或者到音视频结束调试 web-view开发工具调试在开发工具显示面板,右键会出现调试,打开一个调试面板,当然这样是看不到 cgi 请求的,要看请求我们得重新发送请求,如console里面执行页面刷新,或直接再次右键调试,都会触发页面刷新请求重新发送。

真机调试真机调试时,请保证开发工具上登录的微信账号与手机的账号一致。不然可能会出现账号问题(真机调试的账号使用的是你开发工具上的账号)。由于 web-view 组件的层级实在太高,盖住了 vconsole 的调试,所以相当于没有调试工具。不过也有一些办法可以解决:如果其他上下关联的页面是非 web-view 的话,可以在上下关联的页面中查看 vconsole 的信息使用 alert大法使用 whistle(关于 whistle 如何调试下次再具体介绍)

总结

最后的最后,不论在开发工具中显示良好或者不良好,都一定要用真机查看效果,而且 IOS 和 安卓都要看下。 不要太相信你的代码,也不能不相信你的代码