微信小程序:物理返回键和navigateBack的细微区别

背景说明:在业务开发中存着这样一个场景,点击A页面的“一级评论输入框”会跳转评论输入页面B,点击A页面的“他人评论”会弹起小输入框和键盘。

存在问题:在跳转进入B页面后 textarea 输入框会自动聚焦,弹起键盘,若不做任何操作直接点击左上角“取消”按钮返回A页面,则到A页面后,初次点击“他人评论”时小输入框会无法按预期效果跟随着键盘一起弹起。第二次点击才可以按照预期弹起。

发现问题关键:随着多次测试发现,当进入B页面后,输入文字或手动点其他区域让输入框失焦,再返回A页面,则A页面不会出现前述bug。所以将解决问题的关键锁定在如何手动将B页面中 textarea 输入框失焦。

解决问题

首先众所周知的是微信小程序没有DOM这种说法,所以想像web开发中,使用DOM节点自动失焦是不可行的。于是经过查阅文档以后,发现 textarea 存在一个属性 focus,可以通过切换 focus 属性实现聚焦与失焦的效果。

于是在data中定义的 focusFlag 用于控制 focus 的属性值,初始值为 true,在退出当前页面的 onUnload 生命周期里调用 setData,将 focusFlag 置为 false。然后用我的 Android 老爷机测试了一下,乍一看没什么问题。

···
onUnload () {
   this.setData({
       focusFlag: false
   })
}
···

正当以为问题解决了的时候,换了一个酷炫 iPhone 11 来扫码测试了一下,发现问题依然存在,还是不能弹起输入框。并且特别奇怪的是,使用小程序左上角的物理返回键时,一切正常,但是使用左上角的 “取消” 按钮进行返回时,就不行了,怎么会呢??

“取消” 按钮绑定的事件里也设置了setData,将 focusFlag 置为 false ,然后再调用 wx.navigateBack() 啊,有什么问题吗?怎么物理返回键就行,我手动调用 wx.navigateBack() 就不行呢?小丫头片子还两幅面孔呢?

就在我和同事冥思苦想的时候,突然灵光一闪。是不是 使用 wx.navigateBack() 进行返回页面时不会经过 onUnload 生命周期呢?事实证明我在想屁吃, wx.navigateBack() 一样会经过 onUnload 生命周期。那这是为什么呢?陷入了僵局。

于是我再想,我的 Android 老爷机测试没有问题,而 ios 年轻力壮机就不行,这俩除了操作系统不同以外,还有就是运行速度不一致,一个快的飞起,一个慢的一批,是不是系统在处理数据时因为运行环境快慢不同,导致对数据状态的处理完整度上有问题?(我瞎猜的)再进一步想,是不是物理返回键和手动调用 wx.navigateBack() 还真是有细微不同,可能点击物理返回键时系统会对页面状态清理的更加彻底,但是使用 wx.navigateBack() 时可能就会存在状态残留,为了争取尽快进入下一个页面的渲染,把上一个页面的渲染状态到一半就结束了,没完成就算了,反正影响不大,毕竟页面之间是隔离开来的。

于是就再次查找文档,最终发现了解决问题的最终方法:setData 的成功回调函数!你不是要尽快进入下一个页面的渲染吗?我偏要让你完成我的状态渲染以后才能跑!代码如下:

this.setData({
   focusFlag: false
}, () => {
   wx.navigateBack(); 
})

⑧ 到了这一步,问题就彻底解决了。使用的解决办法非常简单,就是很多人常用到会忽略的 setData 的回调函数,但是难点在想清楚整个 bug 出现的原因,定位错误,最终选择最优的解决方案。

记录bug,完结撒花。

posted @ 2021-05-27 15:44  LeoX的爬坑笔记  阅读(902)  评论(0编辑  收藏  举报