问题暴露了
前几天甲方在群里吼了,说app页面一片空白没法审批工作流。我顶着满头大汗在安卓上和ios上分别试了试,最后得出结论是ios环境下某些工作流的页面无法渲染。一时间,我也没有思路。只好用真机连上uniapp看看会不会抛出错误,经过一阵操作果然得到一串错误代码webviewReady[6][5] not matchERROR
。
原来是内存泄漏
经过一番求索确认是内存泄漏了,但是为啥只在ios出现还是有些不解。暂且我还认为是uniapp或者是ios的锅。因为网络上也有类似的帖子并且没有解决方案。要说清楚原委,有必要介绍一下我们的项目背景。
我们的项目是一个无代码平台,类似钉钉,飞书那种定制化的oa系统。客户可以在后台配置各种表单字段,表单类型,就能渲染成复杂的请假工作流,报销工作流。说起来业务还真有点复杂,不过在pc上用了这么久一直没有出过问题。不知为啥在app上就踩了雷了。目前我能想到的是某个工作流配置的表单字段过多就会出现这种情况,简单来说就是dom元素太多了,手机渲染时认为有可能影响手机其他程序正常运行所以就给制止了。
真相亮了
也怪我笨,在摆烂了几天之后,我才想到用排除法确认是不是某个表单组件渲染的问题。然后自己写了个测试页面把目前用到的所有字段类型都高压测试一番,单行文本,多行文本,下拉框,日期,时间等等,显示10个,100个,1000个分别测试。最后果然锁定到日期时间这个表单字段,只要超过30个就能把页面搞崩。经过排查原来是我把单行文本和日期时间放到了同一个组件里面,而日期时间是个弹窗组件是百分百渲染的,如果刚好某个工作流表单有个报销明细单,五列六行就是30个输入框,直接就能把页面干崩。解决方案很简单,把日期时间和单行文本拆分开单独渲染,能解决眼下这个问题。
事情解决了吗?
事情真的就这样简单解决了吗?当然不是。如果刚好有个工作流恰恰就是要在五列六行里输入30个日期时间怎么办。而且不仅仅是日期时间,时间,选择城市,下拉框以及其他弹窗的字段都会有这个问题,渲染个数上限也就100个左右。于是我试了一个200个字段的表单,果然在ios上出现了一片空白,还是那个熟悉的画面。
放大招
最终我想到了两个方案,都是从减少弹窗渲染入手。一个方案是把所有的弹窗类型整理出来,把每种弹窗组件放到最外层,用全局监听或者状态管理控制打开弹窗和传值。相当于一种弹窗只渲染一次,我感觉这个方案比较正统,但是实现起来挺麻烦,主要监听和传值我没想清楚。索幸就放弃了。另一个方案比较投机,把所有的弹窗组件都独立出来,不用picker包着。然后在渲染表单的时候不加载弹窗组件,再利用v-if控制显隐。这个方案有两个弊端,一个是v-if后和拿到dom是有一个时间差的,但是0.1秒的时间肉眼不太能感知,另一个就是要把插件市场下载的一些组件自己重新写一遍,要不然显隐控制很不灵活。结果您肯定也听出来了,我采用了第二个方案。
结语
如果您刚好遇到类似的困扰或许能得到些启示。也或者有哪位大神有更好的方案,还望指教。
做开发是一件有意思的事情,同一个需求可以有不同的设计思路和实现方式,这条路走不通可以走另一条。当陷入死胡同时,静下心来歇一歇,说不定就能打开思路,找到一条曲径通幽的小路。