【问题标题】:Alternatives to re-flow and re-paint重流和重绘的替代方案
【发布时间】:2013-02-18 18:53:25
【问题描述】:

我有read on SO 和其他地方,重新绘制和重新流动对于浏览器来说是昂贵的。

我很好奇 CSS/JS 替代 re-paint/display:none 和 re-flow/visibility:hidden 对浏览器的计算要求不高。

为了清楚起见,如果我错了,请纠正我,常见的回流场景是当您在要切换显示的元素上设置 display:none 时,例如下拉菜单。重排意味着浏览器首先“流动”,即将元素和下面的一切显示为可见内容,然后必须重新流动所有内容,因为下拉菜单需要隐藏。

也欢迎评论回流和重绘对性能的影响是否真的是人们需要关心的事情。

【问题讨论】:

  • 如果要改变显示的内容,至少需要回流和重绘一次。您可以做的最好的事情是通过不将 DOM 更改与计算属性读取交替来最小化重排次数
  • 在一个典型的网页上(例如,这里的这个 - Stackoverflow),在它开始看起来生涩之前想要使用的display:none 的典型上限是多少?
  • 永久隐藏的 DOM 元素不会导致回流。痛苦的是“移除这个元素。容器有多大?移除这个。它现在有多大?好的,也移除这个。现在怎么办?”
  • 重点是,如果一次移除多个元素,如果浏览器可以避免除最后一次回流之外的所有元素,那么最终可能只会得到一次回流。
  • 我很确定这应该不是问题。看看浏览器能以多快的速度创建 1000 个 div,让它们不可见,然后再让它们可见:jsfiddle.net/howderek/aDzgc

标签: javascript html css repaint reflow


【解决方案1】:

我认为你误解了那句话。

如果您要动态生成元素,请考虑以下两个场景:

  1. 生成一个元素,将其添加到 DOM。重复。
  2. 首先创建一个 DOMDocumentFragment。将元素添加到片段。重复。将片段添加到 DOM。

方法 1 将为您添加的每个元素重新绘制。方法 2 最后只会进行一次重绘。如果要添加的元素数量很少,方法 1 可能没问题。如果要添加许多节点,方法 2 会快得多。

这就是 重绘很昂贵的意思


也许这是一种看待它的好方法:

重绘的基本成本为 100。创建一个 DOM 元素并附加它的成本为 1。如果您对 7 个元素执行方法 1,您的成本将为 (1 + 100) * 7 = 707。如果您正在执行方法 2,您的成本将是:1 * 7 + 100 = 107。这要低得多。这些数字仅用于说明。可能还有很多事情要做,但我认为这是一个很好且简单的方法来查看重绘性能。

【讨论】:

  • 所以添加然后从 DOM 中删除加载程序 gif 是重新流动的一个很好的例子吗?那不可能很贵。我想如果 JS 重复添加/删除/隐藏/显示大量 HTML,那么“费用”可能变得相关。
  • @timpeterson 添加 gif 确实不会影响性能(除非它取代 10000 多个元素)
  • @FritsvanCampen 谢谢,所以寻找重新绘制/重新流动的替代方案甚至是一个合理的目标吗?
  • 我认为不存在这样的事情。如果您遇到性能问题,请考虑减少屏幕上的元素数量。
【解决方案2】:

没有简单的公式。首先,每个浏览器都有自己的方式来处理重排和重绘。通常,浏览器会尽量推迟重排,因为您知道,它们可能非常昂贵。

一般来说,请记住以下操作总是会触发回流:

  • 通过添加、删除或移动节点来更改 DOM 树。
  • 更改 CSS 计算属性,例如 offsetWidth
  • 使用 getComputedStyle(或旧 IE 上的 currentStyle)读取计算的 CSS 值

(见When does reflow happen in a DOM environment?。)

设置样式通常会导致重排,但如果更改不会影响其他元素的位置或尺寸,浏览器会尽量避免它[需要引用]

若想了解回流的乐趣,请参阅Will it reflow?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-07
    • 1970-01-01
    • 2015-05-30
    • 1970-01-01
    • 2020-09-20
    • 2018-11-14
    • 2020-04-08
    • 2018-07-14
    相关资源
    最近更新 更多