【问题标题】:Javascript Performance - Dom Reflow - Google ArticleJavascript 性能 - Dom Reflow - Google 文章
【发布时间】:2010-12-23 02:09:45
【问题描述】:

有人可以向我证明here(复制如下)关于在更改它们然后重新插入它们之前删除 dom 元素的建议更快。

通过证明,我希望看到一些数字。他们研究这个很好,但我认为这篇文章非常薄弱,没有详细说明“问题”到底是什么以及解决方案如何解决速度方面的问题(如文章标题加速 JavaScript)

文章....

外流 DOM 操作

这种模式让我们可以创建多个元素并将它们插入到 DOM 中,从而触发单个回流。它使用称为 DocumentFragment 的东西。我们在 DOM 之外创建了一个 DocumentFragment(因此它是不合流的)。然后我们创建并添加多个元素。最后,我们将 DocumentFragment 中的所有元素移动到 DOM 中,但会触发一次重排。 问题

让我们创建一个函数来更改元素内所有锚点的 className 属性。我们可以通过简单地遍历每个锚点并更新它们的 href 属性来做到这一点。问题是,这可能会导致每个锚点的回流。

function updateAllAnchors(element, anchorClass) {
  var anchors = element.getElementsByTagName('a');
  for (var i = 0, length = anchors.length; i < length; i ++) {
    anchors[i].className = anchorClass;
  }
}

解决办法

为了解决这个问题,我们可以从 DOM 中移除元素,更新所有锚点,然后将元素插入到原来的位置。为了帮助实现这一点,我们可以编写一个可重用的函数,它不仅可以从 DOM 中删除一个元素,还可以返回一个函数,将元素插入到其原始位置。

/**
 * Remove an element and provide a function that inserts it into its original position
 * @param element {Element} The element to be temporarily removed
 * @return {Function} A function that inserts the element into its original position
 **/
function removeToInsertLater(element) {
  var parentNode = element.parentNode;
  var nextSibling = element.nextSibling;
  parentNode.removeChild(element);
  return function() {
    if (nextSibling) {
      parentNode.insertBefore(element, nextSibling);
    } else {
      parentNode.appendChild(element);
    }
  };
}

现在我们可以使用这个函数来更新元素中的锚点,并且只在我们移除元素和插入元素时触发回流。

function updateAllAnchors(element, anchorClass) {
  var insertFunction = removeToInsertLater(element);
  var anchors = element.getElementsByTagName('a');
  for (var i = 0, length = anchors.length; i < length; i ++) {
    anchors[i].className = anchorClass;
  }
  insertFunction();
}

【问题讨论】:

    标签: javascript performance


    【解决方案1】:

    这与使用 documentFragments 初始化元素而不是 dom 或多或少相同。文档片段最终会更快,因为它们需要担心的结构和实际渲染更少。

    以下是 John Resig 关于文档片段(目前在 jquery 中使用)的性能优势的一些注释:

    http://ejohn.org/blog/dom-documentfragments/

    【讨论】:

      【解决方案2】:

      除了查看页面之外,没有可靠的方法来判断回流何时完成。

      计算所花费的时间几乎与一次性或一个一个地添加或更改元素相同。脚本不会在元素之间等待浏览器,浏览器会赶上来。

      有时您想立即看到某些内容,即使渲染整个内容需要更长的时间 - 有时您想等待更长的时间并在准备好时显示全部内容。

      如果您无法判断哪个更好,请让设计师查看一对一和一次性版本 - 但不要问两个设计师!

      【讨论】:

        【解决方案3】:

        我在页面上放了一些链接,并测试了文章中的方法,与在页面中设置类名的元素进行比较。我在 Firefox 3、IE 8 和 Chrome 3 中尝试过。

        我为具有不同颜色和不同字体大小的链接创建了类。由于不同类的链接文本大小不同,我确信页面确实需要重排。

        对于任何合理数量的链接(最多几千个),删除和添加元素都会稍微慢一些。

        对于大量链接(10 000),删除和添加元素会稍微快一些。

        但是,差异很小。您必须拥有数千个链接才能注意到任何差异,而在 10 000 个链接中仍然只有 20% 左右的差异。

        所以,我发现你不能指望这种方法有任何戏剧性的变化。如果您有性能问题,可能还有其他方法可以提供更好的结果。例如,我会尝试更改父元素的类名而不是所有子元素,然后让 CSS 完成工作。我之前做过的测试表明,这可以快十倍左右。

        【讨论】:

          【解决方案4】:

          您会发现很难从 javascript 分析中获得有意义的数字,因为您实际上是在保存不会在大多数分析工具中显示的重绘和重流。您可以使用Firebug paint events extension 直观地显示您节省了多少重绘。

          【讨论】:

          • 不错的扩展,但是这两个示例似乎都为我做了相同数量的重绘。任何机会你都可以在 pastebin.me 上做一个演示:)
          • 我承认扩展会大大降低速度,因此有时很难看出计算量大的操作的差异,例如谷歌地图缩放。
          【解决方案5】:

          简短的回答是,对实际页面的 DOM 的更改会触发 Javascript 事件、CSS 评估、更改的传播会影响对其周围 DOM 其余部分的解释等。不断变化的断开连接的节点没有这样的东西连接到它们,并且对它们的操作要便宜得多。

          打个比方:如果您是一名制作《玩具总动员 4》的动画师,在接近最终的渲染中,您看到需要对场景的织物物理特性进行更改,您会在制作完整细节的同时进行更改吗?重新渲染以检查场景,或者在进行这些更改时关闭纹理和颜色并降低分辨率?

          【讨论】:

          • 我想要数字。好处在哪里。理论很棒。就像伊拉克有 WOMD 一样,看看发生了什么。我仍然看不到它如何使 js 更快。我已经对其进行了分析,但看不到任何好处。只是想知道我错过了什么。
          • @redsquare:那篇文章的标题具有误导性,并且在某些方面不准确。它不一定会使 JS 更快……它使浏览器更快地渲染 DOM。换句话说,JS 可以运行得一样快(甚至更慢),但页面看起来会更快,因为浏览器需要花费更少的时间来重排和重绘。重排和重绘是浏览器呈现 HTML 和 CSS 的方式。 JS 性能与浏览器渲染性能不一样。例如,即使您的网站没有 JS,表格的渲染成本也很高。
          • @redsquare:我认为他们称之为“加速 JavaScript”的原因是因为 JS通常是触发重排和重绘的东西。换句话说,通过更改您的 JS 代码,您可以使页面显示得更快。但它的出现并不是因为 JS 更快,而是因为浏览器的重排和重绘减少了。例如,操纵 DOM 的 Java 小程序可能同样糟糕,因此称其为“JavaScript 速度”是不准确的。真的是渲染速度。
          • @redsquare: P.S.我相当肯定,分析 JS 代码几乎没有差异,因为您不应该测量 JS 代码。您应该测量浏览器渲染所花费的时间,而这更难分析。
          猜你喜欢
          • 2012-03-03
          • 1970-01-01
          • 2020-03-20
          • 1970-01-01
          • 2011-05-20
          • 2021-12-12
          • 2011-11-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多