微信h5页面开发遇到的坑

原创 留住回首 随笔 微信h5 481阅读 2018-04-25 09:55:48 举报

一、 长按图片为base64的图片,识别图中的二维码时,base64的字符个数有限制

经过测试大于大概为258286字符(大约500KB)的时候,在识别图时可以弹出正常的菜单,但是点击菜单项“识别图中二维码”则无反应。

需求背景: 拓展业务时,都会生成一个二维码页面用于分享给别人; 而二维码页面包含有,二维码图片,公司logo图,背景图,动态产品介绍文案 等构成的一个页面。

用于分享出去的东西最好的预期是,能把整个页面转换为图片分享出去效果是最好的,而不单单只分享一个二维码图片。所以就有以下需求点需要解决:

  • 把页面转换为图片
  • 让微信能正常识别图中的二维码

利用微信内置的长按功能即可以实现以上需求。在长按后,弹出来的菜单中,可以自己选择“保存为图片”,或者点击“识别图中二维码”直接进入推广页,或者也可以直接发送给朋友。

根据以上需求点,那么问题来了。

页面如何转换为图片呢?

通过html2canvas把页面转换为canvas,然后在通过canvas.toDataURL方法转换为base64图即可

用到的技术为html2canvas

如何使用呢?

直接在自己项目中安装

在项目中引用

把转换出来的base64图,替换掉页面即可,用户是无感知的。

那么问题来了,通过canvas.toDataURL 转换出来的base64字符过长,超出了微信base64字符限制,这怎么办呢?

可以利用canvas.toDataURL 转换为image/jpeg 然后添加第二个参数,改变图片质量,把字符将到限制以下即可。

更多详细的toDataURL方法的使用可以参考MDN文档

二、页面首次登录发起的微信静默登录后,后台重定向回到当前页面,要点击两次返回才能回到上一个页面问题。

要分析整个问题,得先理解微信的静默登录的流程是如何的,流程如下:
微信静默登录的地址为:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=[企业号appId]&redirect_uri=[后台回调url]&response_type=code&scope=snsapi_base&state=[前端页面url]#wechat_redirect

  • 第一 ,当页面请求某个后台接口时,后台接口会返回一些东西,让你知道用户未登录;通常的做法是,后台会返回状态码401,然后前端根据401状态吗,执行location.replace([微信静默登录地址]),让页面加载这连接就会执行静默登录。
  • 第二,加载以上连接后,微信会把响应的一些参数code和参数state指定的前端页面拼接到传入的后台回调url,然后执行这个后台url请求。
  • 第三,请求后台时,后台会根据拼接传给他的参数,去获取用户的openid,和access_token,成功后,会重定向回到state参数指定的前端页面url。

原因分析:

后台重定向是无法替换掉历史记录的,所以导致这个问题。
对于这个问题的误解:当发起微信静默登录时,采用location.replace()时,一直以为,为什么不会替换掉历史记录,问题的考虑点就错了,问题点不在这,因为问题点是重定向不会替换掉历史记录。所以当用户登录成功后,点击第一次返回,会回到当前页,再次点击返回时,才能回到上一个页面,所以会出现,点击2次返回才能回到上一个页面问题。

那么问题来了,如何解决这个问题呢?

假如有两个页面A(不需要登录态),B(需要登录态)

首先得分析一下页面的历史记录如下:

  • 当进入页面A时,历史记录为1,当点击跳转到B页面时,执行了微信静默登录,此时历史记录+1 即为2。
  • 然后登录成功后重定向回到B页面,此时历史记录再+1 即为3了。

我们可以重定向回到B页面时,还未进入到B页面,就让历史回退history.go(-2)到A页面(此时历史记录为1),然后A页面在根据一些参数来判断,跳转到B页面(此时的历史记录为2),即可实现当点击B页面可以直接回到A页面。

ps:这里我的项目主要用到了中间页进行登录了。没有中间页的情况,直接history.go(-1)即可。

还是直接上代码吧,代码(截取的是自己vue项目的一个实现,部分代码)如下:

vue项目为单页面应用,所以把逻辑放到全局路由守卫(当进入A,B页面时都会执行,即进入A或B路由时,首先会执行的逻辑判断

三、iphone6和iphone6s中发现,静默登录后页面不刷新,或者白屏

假如进入A页面时发起静默登录,成功登录后回调到A页面,要是A页面连接不变,A页面就不会刷新,导致,假如刚进入A页面,还未渲染DOM时,就发起静默的登录,重定向回来时,看起来就是白屏效果,或者假如你传给state的参数大于128字节时(即字符长度为64)。超过的话,会被截取掉。

想要预防state大于限制被截取掉,可以把前端的回调地址不要放在state参数里,而是自己取一个参数拼接放在后端的回调参数redirect_uri里即可,然后在跟后端约定就好,拼接如下:

即静默登录成功后,后台到时候想要302重定向回来前端页面,取的参数值应该为上边的redirectUrl参数了,而不是微信拼接的state参数了,这个跟后台约定好即可。

解决方案:

发起静默登录时,在参数state指定的前端回调页面连接里,加入任意参数即可。添加如下:

四、ios左右边缘滑动返回前进页面动画与h5用户自定义页面切换动画冲突问题

导致滑动切换页面时执行了ios的动画之后又执行自定义动画。看起来就是闪了一下自定义动画。

解决方案:

监听左右滑动手势和touchstart事件清除掉自定义动画即可。

同时加入滑动后多少ms后恢复动画,不然滑动后就真的没有自定义动画了 ,已防止用户不是边缘滑动时清除掉的自定义动画恢复。

多少ms 后恢复 建议设置为切换动画执行时间的两倍即可。

上边为什么要监听touchstart事件呢,因为经过测试发现滑动边缘返回或前进时,不一定执行滑动事件,因为封装的滑动事件是有最小距离的,超过才执行的。

然后又为了防止用户触摸屏幕时会执行touchstart事件从而导致切换动画清除掉,在click事件发生时要回复动画。

截取vue项目中的部分代码如下:

ps: 这个不是微信里的坑,但是也一起记录了,触摸事件可以自己添加,vue-touch触摸插件,上边的v-swipe指令我是自己在项目里通过 Vue.derective('swipe',{...}) 这种方式自己添加的。

参考

HTMLCanvasElement.toDataURL()

html2canvas

微信网页授权

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复