2018-09-13 回流reflow 重绘repaint 重排reflows

  • 浏览器加载时会发生什么

    详情可以查看这篇文章
    首先浏览器会解析html 生成DOM树;
    接下来浏览器会将CSS部分解析成样式结构体;
    完成以上两步之后将 dom tree 和样式结构体结合,生成render tree;
    在render tree生成后 浏览器开始绘制页面。
    需要注意的是
    不会用于呈现,而且不会影响呈现的隐藏节点不会包含到render tree
    例如display:none,而visibility:hidden则会包含到render tree;

  • 回流何时发生的?

    首先要明确

    1. 页面至少会发生一次回流
    2. 回流必定重绘,重绘不一定回流

    下面所有都会引起回流

    1. 调整窗口大小(Resizing the window)
    2. 改变字体(Changing the font)
    3. 增加或者移除样式表(Adding or removing a stylesheet)
    4. 内容变化,比如用户在input框中输入文字(Content changes, such as a user typing text inan input box)
    5. 激活 CSS 伪类,比如 :hover (IE 中为兄弟结点伪类的激活)(Activation of CSS pseudo classes such as :hover (in IE the activation of the pseudo class of a sibling))
    6. 操作 class 属性(Manipulating the class attribute)
    7. 脚本操作 DOM(A script manipulating the DOM)
    8. 计算 offsetWidth 和 offsetHeight 属性(Calculating offsetWidth and offsetHeight)
    9. 设置 style 属性的值 (Setting a property of the style attribute)
      原文链接:回流与重绘:CSS性能让JavaScript变慢?
  • 如何减少回流带来的影响,优化性能

    1. 如果想设定元素的样式,通过改变元素的 class 名 (尽可能在 DOM 树的最末端)(Change classes on the element you wish to style (as low in the dom tree as possible))
    2. 避免设置多项内联样式(Avoid setting multiple inline styles)
    3. 应用元素的动画,使用 position 属性的 fixed 值或 absolute 值(Apply animations to elements that are position fixed or absolute)
    4. 权衡平滑和速度(Trade smoothness for speed)
    5. 避免使用table布局(Avoid tables for layout)
    6. 避免使用CSS的JavaScript表达式 (仅 IE 浏览器)(Avoid JavaScript expressions in the CSS (IE only))
      原文链接:回流与重绘:CSS性能让JavaScript变慢?
  • 重绘repaint 重排reflows

    重绘repaint 是一个元素外观的改变所触发的浏览器行为,例如改变vidibility、outline、背景色等属性。浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。重绘不会带来重新布局,并不一定伴随重排。
    重排reflows 是更明显的一种改变,可以理解为渲染树需要重新计算。下面是常见的触发重排的操作

  1. DOM元素的几何属性变化
    当DOM元素的几何属性变化时,渲染树中的相关节点就会失效,浏览器会根据DOM元素的变化重建构建渲染树中失效的节点。之后,会根据新的渲染树重新绘 制这部分页面。而且,当前元素的重排也许会带来相关元素的重排。例如,容器节点的渲染树改变时,会触发子节点的重新计算,也会触发其后续兄弟节点的重排, 祖先节点需要重新计算子节点的尺寸也会产生重排。最后,每个元素都将发生重绘。可见,重排一定会引起浏览器的重绘,一个元素的重排通常会带来一系列的反 应,甚至触发整个文档的重排和重绘,性能代价是高昂的。
  2. DOM树的结构变化
    当DOM树的 结构变化时,例如节点的增减、移动等,也会触发重排。浏览器引擎布局的过程,类似于树的前序遍历,是一个从上到下从左到右的过程。通常在这个过程中,当前 元素不会再影响其前面已经遍历过的元素。所以,如果在body最前面插入一个元素,会导致整个文档的重新渲染,而在其后插入一个元素,则不会影响到前面的 元素。
    3.** 获取某些属性**
    浏览器引擎可能会针对重排做了优化。比如Opera,它会等到有足够 数量的变化发生,或者等到一定的时间,或者等一个线程结束,再一起处理,这样就只发生一次重排。但除了渲染树的直接变化,当获取一些属性时,浏览器为取得 正确的值也会触发重排。这样就使得浏览器的优化失效了。这些属性包括:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、 clientTop、clientLeft、clientWidth、clientHeight、getComputedStyle() (currentStyle in IE)。所以,在多次使用这些值时应进行缓存。
    此外,改变元素的一些样式,调整浏览器窗口大小等等也都将触发重排。
    开发中,比较好的实践是尽量减少重排次数和缩小重排的影响范围。
如何减少重排带来的影响
  1. 将多次改变样式属性的操作合并成一次操作。
  2. 将需要多次重排的元素,position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位。
  3. 在内存中多次操作节点,完成后再添加到文档中去。例如要异步获取表格数据,渲染到页面。可以先取得数据后在内存中构建整个表格的html片段,再一次性添加到文档中去,而不是循环添加每一行。
  4. 由于display属性为none的元素不在渲染树中,对隐藏的元素操作不会引发其他元素的重排。如果要对一个元素进行复杂的操作时,可以先隐藏它,操作完成后再显示。这样只在隐藏和显示时触发2次重排。
  5. 在需要经常取那些引起浏览器重排的属性值时,要缓存到变量。

相关链接.

页面重绘和回流以及优化
浏览器的重绘(repaints)与重排(reflows)

你可能感兴趣的:(2018-09-13 回流reflow 重绘repaint 重排reflows)