框架:基于VUE2的UNI-APP
实习工作期间,在使用UNI-APP开发微信小程序的时候遇到了个很奇怪的问题。
在列表项仅渲染了200+后,清空列表项会存在明显的卡顿。
通过Performance工具分析可以看到。耗时主要发生在flushCallbacks这个回调函数中。
再次查看渲染执行结构,发现微信小程序的渲染递归回调的。也就是说,只有当最里层的组件渲染完之后,才会执行回调通知上一层组件。
所以,我初步认为问题就出现在了组件层级上,因此我去除了组件化后了,再次进行测试。
去除组件化后,渲染时长也确实降下来了。
但是我问过很多大佬,他们都说组件化虽然有影响,但不至于影响这么大。而且在日常团队开发中,如果剔除了组件化,那么将会增加后期的维护成本。
所以,尽管这个问题看似已经解决了,但我觉得还是不够完美。而且很多人使用uniapp开发时也没有出现这个问题。
于是我再次对代码渲染数据进行分析。
通过断点调试发现,变更的内容确实只有147个
但是,当渲染跑到了notify函数时,发现了依赖项的数量有问题。deps数组记录的依赖项中的subs数组居然高达了5000+个依赖项
最后通过多次断点调试检查,发现到了可疑点。基本在每个组件的内部都存在这个主题颜色的依赖项。并且在页面进行渲染的时候,也触发了这个依赖项的更新。
检查项目代码发现,主题色这个对象,是通过全局mixin导入到了每个组件里面,也就是说,每个组件的内部都会存在这个主题色的计算属性。
所以才会出现短短一个列表项,却出现了5000+个依赖项的原因(其中大部分都是这个主题色的相关依赖项)
为了校验猜想,我把这个全局mixin给注释了。最后发现,耗时确实也降下来了(24784.1ms降到了265.4ms)
再次查看依赖项,subs的依赖项也确实降下来了。
总结解决方法:
1.去除组件化开发(因为v-for每生成一个组件,都会存在全局mixin的数据,所以去除组件化也可以达到避免依赖增多的问题)
2.剔除全局mixin(或把数据放到data中,并且对数据进行冻结,避免出发响应式更新)
最后引用vue官方的一句话。各位使用全局mixin时,一定要!!!!格外小心!!!!
再送上一张关于微信小程序的setData约束建议