什么是重绘与重排


回流:

构造完渲染树后,会将DOM节点与对应的CSS结合,同时我们要进入布局阶段,还需要计算他们在设备视口ViewPort内的确切位置的大小,这个阶段就是回流

谷歌开发者文档

重绘:当DOM变化影响元素的几何属性(宽高边距等),浏览器会重新绘制受影响的部分属性到屏幕中,这个过程叫 “重绘”.

JavaScript高性能

浏览器下载完页面中的所有组件-HTML,JS,CSS,图片,之后会生成两个内部数据结构:


DOM树:表示页面结构

渲染树:表示DOM节点如何展示


DOM树中的每个需要现实的节点在渲染树中至少存在一个对应的节点。

渲染树中的节点被称为 “帧” 或者 “盒” ,一旦DOM盒渲染树构建完成,浏览器就开始绘制页面元素。


当DOM变化影响的元素的几何属性(宽和高)-比如改变边框宽度导致行数增加-浏览器需要重新计算元素的几何属性。浏览器会使渲染树中收到影响的部分失效,并重新构造渲染树,这个过程称为 “重排(reflow)”

完成重排后,浏览器会重新绘制受影响的部分到屏幕中,称为“重绘(repaint)”,并不是所有的DOM变化会影响元素的几何属性。


重排何时发生:

重排何时发生

最小化重绘和重排:

  • 延迟访问布局信息:合并多次改变,一次修改class而不是内联
  • 适当使用display
  • 创建文档片段:遍历和重排最少
  • 创建节点备份
  • 缓存布局信息
  • 脱标
  • 减少使用:hover伪选择器
  • 事件委托
总结

什么影响布局/回流?

以下所有属性或方法,当在 JavaScript 中请求/调用时,将触发浏览器同步计算样式和布局*。这也称为回流或布局抖动,是常见的性能瓶颈。

一般所有同步提供布局指标的API都会触发强制回流/布局。继续阅读以了解更多案例和详细信息。

元素 API

获取盒子指标
  • elem.offsetLeft, elem.offsetTop, elem.offsetWidth, elem.offsetHeight,elem.offsetParent
  • elem.clientLeft, elem.clientTop, elem.clientWidth,elem.clientHeight
  • elem.getClientRects(),elem.getBoundingClientRect()
滚动的东西
  • elem.scrollBy(),elem.scrollTo()
  • elem.scrollIntoView(),elem.scrollIntoViewIfNeeded()
  • elem.scrollWidth,elem.scrollHeight
  • elem.scrollLeft,elem.scrollTop也, 设置它们
设置焦点
还…
  • elem.computedRole,elem.computedName
  • elem.innerText来源

获取窗口尺寸

  • window.scrollX,window.scrollY
  • window.innerHeight,window.innerWidth
  • window.visualViewport.height/width/offsetTop/offsetLeft(源码)

文档

  • document.scrollingElement只强制风格
  • document.elementFromPoint

形式:设置选择+焦点

  • inputElem.focus()
  • inputElem.select(),textareaElem.select()

鼠标事件:读取偏移数据

  • mouseEvt.layerX, mouseEvt.layerY, mouseEvt.offsetX, mouseEvt.offsetY(来源)

调用 getComputedStyle()

window.getComputedStyle()通常会强制重新计算样式。

window.getComputedStyle()通常也会强制布局。

gCS() 强制布局条件的详细信息

获取Range维度

  • range.getClientRects(),range.getBoundingClientRect()

SVG

相当多的属性/方法强制,但我没有列出详尽的清单。此列表不完整:

  • SVGLocatable: computeCTM(),getBBox()
  • SVGTextContent: getCharNumAtPosition(), getComputedTextLength(), getEndPositionOfChar(), getExtentOfChar(), getNumberOfChars(), getRotationOfChar(), getStartPositionOfChar(), getSubStringLength(),selectSubString()
  • SVG使用:instanceRoot

使用下面的“铬源树链接”自行探索!

内容可编辑

  • 很多很多东西,…包括将图像复制到剪贴板(来源

附录

  • 仅当文档已更改并使样式或布局无效时,重排才会产生成本。通常,这是因为 DOM 已更改(修改了类,添加/删除了节点,甚至添加了 :focus 之类的伪类)。

  • 如果强制布局,则必须先重新计算样式。所以强制布局会触发这两种操作。它们的成本很大程度上取决于内容/情况,但通常两种操作的成本相似。

  • 你应该怎么做?好吧,

    More on forced layout

    下面的部分更详细地介绍了所有内容,但简短的版本是:

    1. for强制布局和更改 DOM 的循环是最糟糕的,避免它们。
    2. 使用 DevTools 性能面板查看发生这种情况的位置。您可能会惊讶地看到您的应用程序代码和库代码出现这种情况的频率。
    3. 批量写入和读取 DOM(通过FastDOM或虚拟 DOM 实现)。在帧的开头(非常开始rAF,滚动处理程序等)阅读您的指标,当数字仍然与上次布局完成时相同。

卫报的时间线痕迹。Outbrain 正在反复强制布局,可能是在一个循环中。

跨浏览器

更多关于强制布局


参考

谷歌开发者文档

JavaScript高性能

MDN


Author: xt_xiong
转载要求: 如有转载请注明出处 :根据 CC BY 4.0 告知来自 xt_xiong !
评论
  标题