
课程咨询: 400-996-5531
投诉建议: 400-111-8989
认真做教育 专心促就业
前两天遇到一个前端性能相关的bug,感觉还挺典型的,整理了一下解决过程和思路,写下来分享给大家。
场景是这样的,有一个答题的界面,可以播放音频、填空、提交答案,界面是长这个样子的:
看起来还挺简单吧,但是我们在手机上跑的时候,却遇到了以下问题:
1. 填完空后,提交按钮会由灰色变为蓝色(可提交状态),但是播放完音频后,却无法变蓝
2. 页面较长时,一边播音频一边滚动页面,会出现页面闪烁(短时白屏)
我的第一反应就是:出渲染bug了。因为在一些低端手机上,经常会遇到动态修改页面,渲染没有及时生效,出现花屏或者白屏的情况。
而修改这类bug并没有什么好方法,唯一管用的就是强制浏览器再重绘一次。常用的技术手段比如设置style.visibility="visible",或者是更新一下className。有时候这种“轻度重绘”起不到作用的话,还会修改背景色啦,或者先display:none然后在display:block,目的都是强制触发浏览器的reflow或者repaint,期望它能给渲染正常。
因此我不假思索使出老手段。但是在尝试各种强制重绘后,并没有解决问题1。这我也是能想通的,毕竟是不稳定的hack手段,不生效也是情有可原。
有人会问,是不是逻辑写的有问题啊?经我排查其实并没有逻辑问题,我们是用vue的:class绑定做的样式更新,此时该状态的变量已经更新了,而且class的属性值也更新了,只是视觉上没看到更新而已,还是渲染的问题没错。
此时我有一个胆大的想法:不会是vue的bug吧!猜测如下:vue内部更新class值的时候是不是有什么机制,导致浏览器在某些特殊情况下忽略了这次渲染。其实我并不愿意这样想,毕竟vue已经是一个很稳定的框架了,不至于有这么低级的问题吧,就算真有,应该早就暴漏出来了呀。
但是事实就摆在我眼前,而我还必须解决这个bug,所以还得想办法。
“要不,这里就不用vue绑定了。”
不用vue绑定,自己手动操作更新className。这实在是下下策,我甚至感到有点羞耻。因为我是有代码洁癖的,用vue本身就是为了不手动操作DOM,而现在,却要在用vue一气呵成的代码中插入一段手动操作DOM的代码。简直是一颗老鼠屎,破坏了整个代码的完美度。
上线要紧啊,忍了。于是我把提交按钮这里,改为了手动更新className。问题解决了,提交按钮乖乖变蓝,播放音频的动作不会影响到它了。大家夸我快速解决了问题,而我的良心隐隐作痛。
故事并没有结束,其实,重点才刚刚开始。直到遇到问题2,才让我开始重新审视这个问题。问题2是这样的:在页面高度特别长的时候,会有滚动页面的操作。当正在播放音频的时候去滚动页面,大概在播完音频的那个瞬间(页面还在滚),页面会发生一次严重的抖动,直接白屏一下,然后页面重新正常显示。
这下好了,没法用重绘hack,也没法再用手动操作DOM的恶心方法了。此时,不得不拿出调试利器了:chrome的devtool。在Rendering工具中,勾选Paint Flashing,它能够高亮页面被重绘的区域。
有发现了!在音频播放完毕的时候,提交按钮那块区域竟然发生了一次重绘。这怎么回事呢?它俩隔着老远,而且并没有父子关系,况且提交按钮还是绝对定位放在下面的。我想不到什么原因能让下边的提交按钮发生重绘。
免责声明:本文由达内it培训小编转载自网络,旨在分享提供阅读,版权归原作者所有,如有侵权请联系我们进行删除。