经典面试题:什么是回流和重绘?如何优化?

    |     2020年4月14日   |   web前端技术, 优化   |     0 条评论   |    1350

浏览器渲染一页有两条工作:跑 JS、算 CSS。它们是互斥的。面试里「回流 / 重绘」问的就是:改样式时,浏览器要不要重算几何,要不要重画像素。

回流(reflow):render tree 一部分或全部因为宽高、布局、显示隐藏、或内部文字结构变了,需要重新构建页面。重绘(repaint):宽高、布局、显隐没变,只改外观(颜色、阴影等)。结论:回流必定触发重绘,重绘不一定触发回流。

避免回流的两条大方向:少用会触发布局的属性;把变化关进独立图层,限制计算范围。

一、图层是怎么划分的

DOM 加载完后,浏览器会按一些特殊 CSS(例如 position: absolute | fixed)把页面划成一个个图层。元素在自己图层里变化时,回流和重绘尽量只发生在图层内,减少整页计算。

图层内部大致会:对节点做回流和再布局、算出样式;生成图形和位置;把每个节点画进图层位图;把图层当纹理送到 GPU;再把所有图层合并显示。滥用图层会让合成过多,页面反而卡。图层该给「经常改位置 / 布局」的元素,比如轮播。

概念 触发条件 和对方的关系
回流 reflow 改宽高、布局、显隐、文字结构 一定伴随重绘
重绘 repaint 只改外观,几何不变 不一定回流
独立图层 absolute/fixed、部分 3D transform 等 把计算关进局部,但合成有成本

二、九条可替换写法

  • 用 transform 代替 top / left / margin-top / margin-left 这类位移。
  • 用 opacity 代替 visibility 时,要同时有 translate3d 或 translateZ 才能真正避开回流。实验:不加 transform: translateZ(0) 的 opacity 仍会回流;单用 visibility 往往只重绘;opacity + translateZ/3d 后可以既不回流也不重绘。
  • 不要用 JS 给 DOM 设多条样式,改成切一个 className。
  • 若必须用 JS 设多条样式,先隐藏再改,改完再显示。
  • 不要在循环里读 offsetWidth / offsetHeight / clientWidth / clientHeight。浏览器有回流缓冲栈,写样式会攒一批再刷;反复读几何会强迫立刻刷新栈。把值缓存在循环外。
  • 不要用 table 布局:一行甚至一个单元格更新都可能让整表重布局。
  • 动画速度按业务需要,不必盲目求快。
  • 频繁变化的元素加 transform;视频用 video 标签。
  • 必要时开 GPU 加速,但不能滥用。开加速时最好给当前动画元素一个更高的 z-index,人为干扰复合层排序,减少 Chrome 创建多余复合层。

三、什么是 16ms 优化

多数设备刷新率 60 次/秒(1000/60 ≈ 16.6ms)。每一帧要在约 16ms 内画完,超时就会卡。浏览器一帧里大致按下面顺序干活,少做 Layout / Paint,动画才顺:

  • JavaScript:动画、DOM 操作。
  • Style:算出每个 DOM 该套哪些 CSS。
  • Layout:算大小和位置。网页布局是相对的,一个元素动了会连带其它,这个过程叫 reflow。
  • Paint:在多层上画文字、颜色、图、边框、阴影。
  • Composite:按顺序合并图层,显示到屏幕。

一句话总结:回流改几何、重绘改外观;用 transform/opacity+图层代替 top/visibility,避免循环读布局、避免 table 和逐条改 style,把一帧工作压进约 16ms。

转载请注明来源:经典面试题:什么是回流和重绘?如何优化?
本文链接地址:https://ai.zhousir.top/?p=2645
回复 取消