记一次前端性能优化的案例

简介:

前两天遇到一个前端性能相关的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,它能够高亮页面被重绘的区域。

有发现了!在音频播放完毕的时候,提交按钮那块区域竟然发生了一次重绘。这怎么回事呢?它俩隔着老远,而且并没有父子关系,况且提交按钮还是绝对定位放在下面的。我想不到什么原因能让下边的提交按钮发生重绘。

重头来了,这时我打开了Layers工具,看到的景象让我大吃一惊。看下面的动图吧:

音频播放组件那里的graphics layer竟然如此之乱,在开始播放的时候,发生了较多的层提升和层合并。更为奇葩的时,下方的提交按钮区域也跟着发生了层提升。如果你细细观察,还能看到右上角的那片绿叶子也发生了层提升,你这家伙跟着起哄什么啊。。。

这下问题的症结就比较清楚了,多余的层变动,导致意外的重绘。恰逢页面正在滚动,一下遇到了渲染瓶颈,就出现了闪烁。那么,是什么原因导致的层变动呢?

经过审查代码,查到了问题所在,总结如下:

音频组件的布局方式存在问题,左侧旋转的圆盘是右侧进度条的子元素,通过绝对定位给定到左侧的。并且其高度是大于父元素的,通过父元素的overflow:visible才得以完整显示。大家知道元素间的遮挡以及裁切都可能会生成新的提升层(graphics layer)。而且左侧的圆盘在播放时还会通过transform进行旋转动画,transform也会进行层提升,同时浏览器还会进行层合并的判断,将可以合并的合成一个graphics layer。而这个判断是全局进行的,也就是说页面底部的提交按钮也被计算在内,可能正好命中了某些规则,所以它也被提升为单独的层。

所以我把音频组件进行了重新的布局(减少遮挡与裁切),不让它产生那么多的提升层行为。

至于右上角那个绿叶子,我发现他的z-index为100,感觉根本不需要这么大,改为了2,工作良好,并且不会被提升了。大家知道z-index也是层提升的一个影响因素,很多同学经常随手就写一个很大的z-index,生怕自己的元素被别人盖住。这是一个很不好的习惯,没准哪天就给命中了层提升的规则,引发重绘了。

经过了上面的修改,再次打开Layers面板,发现此时的层已经很规整了,效果如下:

 

感觉很清爽了有木有。而在此修改之后,问题1的根本原因也定位到了(由于层提升而引发了重绘),并且顺势恢复正常。那段让我良心隐隐作痛的代码也可以删掉啦!


本文转自吕大豹博客园博客,原文链接:http://www.cnblogs.com/lvdabao/p/7771763.html,如需转载请自行联系原作者

相关文章
|
3月前
|
前端开发 JavaScript 索引
前端性能优化:虚拟滚动技术原理与实战
前端性能优化:虚拟滚动技术原理与实战
464 80
|
3月前
|
缓存 监控 前端开发
前端性能优化:现代框架的关键策略
前端性能优化:现代框架的关键策略
203 74
|
3月前
|
缓存 前端开发 JavaScript
前端性能优化:打造流畅的用户体验
前端性能优化:打造流畅的用户体验
|
7月前
|
缓存 前端开发 UED
如何优化前端性能以提高加载速度
前端性能优化对提升网站加载速度至关重要,直接影响用户体验、SEO排名和转化率。本文介绍了优化前端加载速度的关键技巧,包括最小化HTTP请求、使用CDN、优化图片、利用浏览器缓存、压缩文件和实现懒加载。通过这些方法,可以显著减少页面加载时间,提高网站的整体性能和用户满意度。
|
8月前
|
前端开发 JavaScript 开发者
前端 CSS 优化:提升页面美学与性能
前端CSS优化旨在提升页面美学与性能。通过简化选择器(如避免复杂后代选择器、减少通用选择器使用)、合并样式表、合理组织媒体查询,可减少浏览器计算成本和HTTP请求。利用硬件加速和优化动画帧率,确保动画流畅。定期清理冗余代码并使用缩写属性,进一步精简代码。这些策略不仅加快页面加载和渲染速度,还提升了视觉效果,为用户带来更优质的浏览体验。
|
10月前
|
缓存 前端开发 JavaScript
利用代码分割优化前端性能:策略与实践
在现代Web开发中,代码分割是提升页面加载性能的有效手段。本文介绍代码分割的概念、重要性及其实现策略,包括动态导入、路由分割等方法,并探讨在React、Vue、Angular等前端框架中的具体应用。
|
6月前
|
人工智能 JavaScript 前端开发
Vue 性能革命:揭秘前端优化的终极技巧;Vue优化技巧,解决Vue项目卡顿问题
Vue在处理少量数据和有限dom的情况下技术已经非常成熟了,但现在随着AI时代的到来,海量数据场景会越来越多,Vue优化技巧也是必备技能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
9月前
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
647 5
|
10月前
|
前端开发 安全 UED
2024年前端性能优化新策略
2024年前端性能优化策略涵盖代码分割与环境变量管理。代码分割通过动态导入和按需加载CSS减少初始加载时间;环境变量管理则确保敏感信息安全,简化多环境配置。结合最新工具和技术,可大幅提升Web应用性能与用户体验。
|
9月前
|
缓存 监控 前端开发
探索前端性能优化:关键策略与代码实例
本文深入探讨前端性能优化的关键策略,结合实际代码示例,帮助开发者提升网页加载速度和用户体验,涵盖资源压缩、懒加载、缓存机制等技术。

热门文章

最新文章