网页 repaint 与 reflow 的区别,如何优化?

236 阅读9分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情

写在前面

相信作为程序员的我们,都知道前端三剑客,HTML、CSS、JS,不仅前端工程师,可能后端工程师勉强也能硬写几行 CSS,CSS 可以说是最容易入门、最难以精通的“坑”,曾经采访过好几个后端工程师,几乎都一致表示后端转向全栈最最让他们打退堂鼓的,都是 CSS,为什么这么说呢?其实 CSS 最大的问题是,很多基础教程对于 CSS 的呈现,基本都是零零散散,单一的呈现效果,而真正到了实际应用,堆叠了很多元素,很多样式的时候, CSS 的很多“奇怪”的特效就会在不知不觉中发挥出来,让非专业的 “CSS 工程师” 现场抓狂。

即使 CSS 非常难以驾驭,但是作为前端工程师的我们,这可是我们赖以吃饭的技能呀,因此,在对于浏览器渲染相关原理的理解后,其实还是能够总结出一些行之有效的规范的,遵循这些规范来走,也就能够最大程度地避开不必要的坑,也能够进一步对相关网页进行优化,提高网页的性能和体验,接下来就让我们一起来了解一下与 CSS 渲染过程息息相关的两个问题 repaint 与 reflow ,看看我们能从中总结出什么 CSS 避坑技巧。

repaint 与 reflow 是什么?

repaint 重绘,重新绘制,顾名思义,在原来的位置重新画上新的东西,主要表示的是颜色变化等触发的 CSS 重新渲染的过程

reflow 重排,也叫回流,重新排列,表达的是在原来的基础上,对元素的相对位置进行重新编排,计算相对应的位置时触发的渲染过程

repaint 和 reflow 什么时候触发?

就目前普遍的网页来看,除了远古时期的静态页面之外的所有现代化页面,基本上都存在非常多的交互逻辑,只要交互逻辑触发了相对应的网页变化,也就会触发 repaint 或者 reflow,也就是说动态网页,随时都会触发 repaint 或者 reflow,比如进行弹窗、添加或者删除某个网页元素,或者播放网页动画等等都是触发 repaint 或者 reflow 的操作

repaint 与 reflow 的区别

repaint 与 reflow 的区别主要是触发方式的不同,元素的外观、比如颜色、背景色、边框颜色等变化,而位置和大小并没有变化,则会触发 repaint ,重新渲染元素的外观,而如果是位置和大小等,以及触发其他元素位置变化的动作,则会触发 reflow。

由于 reflow 会触发元素位置相关的计算,因此相比 repaint,reflow 的消耗更小,因此,我们需要尽量避免不必要的 reflow。

如何优化 repaint 和 reflow

我们都知道发送 repaint 或者 reflow 都会对网页性能造成一定的影响,因此,在满足正常功能的前提下,我们应该想办法尽量减少发生 repaint 和 reflow,这样理论对网页性能会有一定的优化作用

使用防抖和节流优化

在许多网页会存在许多触发式的交互,比如点击按钮、输入框自动搜索等,也就是我们进行操作,网页会同步进行相应反馈的功能,那么这种功能在使用过程中,由于操作的频繁发生,会同步触发频繁的 repaint 与 reflow,因此我们可以通过防抖以及节流两种方式来对相关的反馈动作进行优化。

防抖

防抖,这里可以举一个形象的比喻,很多相机都有防抖功能,那么我们可以想象,每次我们都是左右抖,抖完了之后,再进行拍照,也就是 忽略前面的多次触发,只执行最后一次

例如我们有一个输入框,然后输入框有一个自动搜索关键词的功能,原来是每次关键词变化,立刻进行搜索,那么会触发非常多次的请求,同时也会触发非常多次的页面回显,这个时候,我们就应该采取防抖来进行优化,优化后的效果是,当我们输入停止 500ms 后再进行搜索,并且如果在 500ms 内关键词出现变化,则重新计算时间,直到关键词保持 500ms 没有变化才进行搜索,实例代码如下

var timer = null
function toggle(){
  timer && clearTimeout(timer)
  timer = setTimeout(() => {
   // 执行目的函数
  }, delay);
}

节流

节流我们可以理解为规定单位时间内只能有多少流量,即单位时间内所做的动作的量是一定的,也就是说 当我们执行了某个动作后,一定要等待一定的时间后触发才有效果,例如,当我们网页里有某个按钮作为事件开关时,我们可以对它进行节流优化,这样,在用户非正当操作时,也就是频繁触发按钮时,网页也能够按规定的时间执行正常的逻辑,不会因为频繁触发出现bug,示例代码如下

// 标记是否上锁
var isLock = false
function toggle(){
  // 如果在锁定时间内,直接不执行,退出函数
  if(isLock) return
  // 执行目的函数
  // 加锁,delay 后打开
  isLock = true
  setTimeout(() => {
    isLock = false 
  }, delay);
}

规范书写 CSS 的顺序

这个说法一直备受争议,很多博主一直在讨论和实验验证这个问题,这里作为晚辈我也不过多讨论,秉承着理论的原则,我觉得一方面理论上这种做法是可以达到性能优化的,那么我们也就可以这样做做,另一方面,对于规范 CSS 的写法问题,即使没有优化作用,也依然值得我们学习,规范自己书写 CSS 的方式,不仅便于我们自己调试代码,也能够使得我们在协作开发中相互阅读代码,理解对方的思路,这里就简单列举书写顺序供大家参考,有其他意见的可以多多补充

1、布局相关的属性

例如:display、position、float、left、top、right、bottom、overflow、clear、z-index 等

2、自身属性

例如:width、height、padding、border、margin、background 等

3、文字属性

例如:font-family、font-size、font-style、font-weight、font-varient、color

4、文本属性

例如:text-align、vertical-align、text-wrap、text-transform、text-indent、text-decoration、letter-spacing、word-spacing、white-space、text-overflow 等

5、CSS 等新特性

例如:content、box-shadow、border-radius、transform 等

总结

对于 CSS 这种非常非常基础的技能,其实才是我们最应该花时间规范和优化的东西,因为它太基础了,所以很多时候都被大家所忽略,正式因为它是最基础的,最简单的,我们更应该好好学习如何优化以及如何更加规范地书写他,这样,随着我们项目的不断扩大、项目参与成员不断增多,才不至于让项目成为岌岌可危的 “高楼”,稳扎稳打,才能走得更远

往期好文推荐

HTTP1.0 和 HTTP1.1 有什么区别?

这么简单的需求别再说你不会做了好嘛!(ClipPath)

Websocket 底层是 TCP 还是 UDP?白话版解析 TCP 和 UDP 传输过程

面试官:了解低代码平台吗?(数字孪生低代码平台探索)(五)

面试官:了解低代码平台吗?(数字孪生低代码平台探索)(四)

面试官:了解低代码平台吗?(数字孪生低代码平台探索)(三)

面试官:了解低代码平台吗?(数字孪生低代码平台探索)(二)

面试官:了解低代码平台吗?(数字孪生低代码平台探索)(一)

面试官:说说从输入 URL 到页面显示到底经历了什么,体现一下你的知识广度

面试官:作为前端,服务器相关了解多少?

面试官:HTTPS 采用的是对称加密还是非对称加密?具体说说其加密过程

面试官:说说 Cookie 和 Token 的区别?

面试官:网络安全了解多少,简单说说?(一)

面试官:网络安全了解多少,简单说说?(二)

面试官:网络安全了解多少,简单说说?(三)

面试官:网络安全了解多少,简单说说?(四)

面试官:网络安全了解多少,简单说说?(五)

面试官:网络安全了解多少,简单说说?(六)

面试官:网络安全了解多少,简单说说?(七)

面试官:网络安全了解多少,简单说说?(八)

浅尝 | 从 0 到 1 Vue 组件库封装

面试官:这么简单的正则表达式都不会?

Webpack 打包类库踩坑

面试官:你就只会 npm run build 吗?(Webpack 配置 Vue+Ts)

面试官:连VuePress都没搭过还说开发过组件库?(VuePress 搭建)

面试官: 连 Vue 视图更新都不会写?(Vue视图更新原理【一】)

面试官: 能不能手写 Vue 响应式?(Vue2 响应式原理【完整版】)

面试官:能不能手写 Vue3 响应式(Vue3 原理解析之响应系统的实现)

JS 优雅之道(JS 代码优化小 Tip)

面试官:你真的会用 SVG 吗? (SVG 应用实战)

面试官:说一下这个Loading动画实现思路 (CSS3 实现 Loading 动画)

JS 扫盲题 ( 面试题梳理系列 (一))

面试官:你确定你说的防抖不是节流吗?( 面试题梳理系列 (二))

面试官:除了 HTTP,你还用过什么通信协议?(Websocket 在数字孪生中的应用)

面试官:你真的理解 Event Loop 吗?( JS 事件循环 )

面试官:v-for 中 key 为什么不能用 index,从原理层面聊聊?

面试官:vue-router 的 hash 与 history 哪个模式会刷新页面?

面试官:说说你平时用过的自适应方案(数字孪生可视化自适应方案)

面试官:说一下如何优化过渡动画(数字孪生可视化过渡动画)

写在最后

博主接下来将持续更新好文,欢迎关注博主哟!!
如果文章对您有帮助麻烦亲点赞、收藏 + 关注和博主一起成长哟!!❤️❤️❤️