2

我正在使用 GWT 构建一个性能通常正确的 HTML 应用程序。

有时,它可以在 DOM 中加载许多对象,导致应用程序变慢。我使用 Chrome 开发者工具探查器来查看时间花在哪里(在 Chrome 下,一旦应用程序被编译,即没有 GWT 开销),很明显getAbsoluteLeft()/getBoundingClientRect()方法消耗了大部分时间。

这是 Chrome (com.google.gwt.dom.client.DOMImplStandardBase) 下使用的实现:

private static native ClientRect getBoundingClientRect(Element element) /*-{
  return element.getBoundingClientRect && element.getBoundingClientRect();
}-*/;

@Override
public int getAbsoluteLeft(Element elem) {
  ClientRect rect = getBoundingClientRect(elem);
  return rect != null ? rect.getLeft()
     + elem.getOwnerDocument().getBody().getScrollLeft()
     : getAbsoluteLeftUsingOffsets(elem);
}

这对我来说很有意义,因为 DOM 中的元素越多,计算绝对位置所需的时间就越多。但这令人沮丧,因为有时您只知道应用程序的一部分发生了变化,而这些方法仍然需要时间来计算绝对定位,可能是因为它不必要地重新检查了一大堆 DOM 元素。我的问题不一定是面向 GWT 的,因为它是与浏览器/javascript 相关的问题:

是否有任何已知的解决方案可以改善大型 DOM 元素应用程序的 GWT getAbsoluteLeft/javascript getBoundingClientRect 问题?

我在互联网上没有找到任何线索,但我想到了如下解决方案:

  • (减少对这些方法的调用次数:-) ...
  • 通过 iframe 隔离部分 DOM,以减少浏览器必须评估以获得绝对位置的元素数量(尽管它会使组件难以通信......)
  • 同样的想法,可能有一些 css 属性(溢出,位置?)或一些 html 元素(如 iframe)告诉浏览器跳过 dom 的整个部分或只是帮助浏览器更快地获得绝对位置

编辑 :

使用 Chrome TimeLine 调试器,并在 DOM 中有很多元素时执行特定操作,我的性能平均:

  • 重新计算样式:几乎为零
  • 绘制:近 1 毫秒
  • 布局:近900ms

通过 getBoundingClientRect 方法布局需要 900 毫秒。本页列出了 WebKit 中所有触发布局的方法,包括 getBoundingClientRect ...

由于 dom 中有许多不受我的操作影响的元素,我假设布局正在整个 DOM 中进行重新计算,而paint能够通过 css 属性/DOM 树来缩小其范围(我可以通过 Firebug 中的 MozAfterPaintEvent 看到它例子)。

除了对触发布局的方法进行分组和调用之外,关于如何减少布局时间的任何线索?

一些相关文章:

4

2 回答 2

6

我终于解决了我的问题:getBoundingClientRect在应用程序中触发了整个布局事件,这需要多次通过繁重的 CSS 规则。

事实上,布局时间与 DOM 中的元素数量并不成正比。你可以用浅色画出几十万个,布局只需要 2 毫秒。

在我的例子中,我有两个 CSS 选择器和一个背景图像,它们匹配了数十万个 DOM 元素,这在布局过程中会消耗大量时间。通过简单地删除这些 CSS 规则,我将布局时间从 900 毫秒减少到 2 毫秒。

于 2012-11-11T21:35:24.400 回答
-1

您问题的最基本答案是使用惰性评估,也称为延迟评估。原则是,只有当它所依赖的东西发生变化时,你才评估一个新的职位。它通常需要相当多的代码来设置,但一旦完成,使用起来会更干净。您将对某物(例如窗口大小)进行一项分配,然后所有新值都会自动传播,并且只有需要传播的值。

于 2012-11-05T14:40:46.650 回答