liangbus / blogging

Blog to go
10 stars 0 forks source link

关于重绘、回流 (Repaint & Reflow) #18

Open liangbus opened 4 years ago

liangbus commented 4 years ago

这两个词,相信有一定基础的童鞋都不会陌生,尤其是在性能优化方面,更是高频词汇

在讨论之前,我们先来回顾一下页面的渲染过程

  1. 我们都知道我们的网页是使用流式布局,俗称文档流
  2. 浏览器会把 HTML 结点解析成 DOM Tree,CSS 解析成 CSSOM(CSS Object Model),二者结合就会产生渲染树 Rendering Tree(此时还没有真正的渲染,display: none 的节点也不会加入渲染树,二者是并行的过程).
  3. 有了渲染树之后,浏览器的渲染引擎就结合样式把所有的 DOM 节点,计算各个元素盒子的大小位置等信息,然后渲染成我们所看到的页面,这个过程就叫布局(Layout,或 Reflow 回流),最后就是绘制(Paint)

上面可以看出,布局和绘制是初始化必须经过的过程,那么回流和重绘,就是触发相关元素再次初始化的一个过程

触发回流的操作

  • 页面初始化
  • 浏览器窗口大小变更
  • 元素尺寸或者位置发生改变
  • 元素内容变更(文字,图片大小,Dom 结构)
  • 元素字体大小变更
  • 增加删除可见的 Dom 元素
  • 触发伪类(如 :hover)
  • 设置元素 style 值

触发重绘的操作

仅改变元素的表面样式,不改变其位置及几何属性,比如常见的样式有: color, border-style, visibility, background-color, background-image, background-position, background-repeat, text-decoration, outline-color, outline-width, border-radius, box-shadow 等等

回流必将引起重绘,重绘不一定会引起回流。

所以为了提升性能,我们要减少重绘和回流,怎么减少?常见的方法有:

除此之外,最近还被问到另外一种方法,既然是多次变更元素样式,能不能收集起来一次性变更 当时我的回答是说可以切换 class,那万一是需要计算的样式呢?那写行内样式??

这时候,就祭出大杀器: cssText 它的用法很简单: document.getElementById("d1").style.cssText = "color:red; font-size:13px;";

我们可以通过示例瞅瞅 codepen demo

cssText 会覆盖掉元素的行内样式,但是不会覆盖样式文件里面的类样式,所以行内样式需要一次性设置全部的

其实这篇东西,就是为了记录这一个点,当时没回答好,耿耿于怀,写个笔记,上面的权当复习

参考: 你不知道的浏览器页面渲染机制