【问题标题】:jQuery width() method performancejQuery width() 方法性能
【发布时间】:2012-09-07 00:09:33
【问题描述】:

我是一个 jQuery 菜鸟,试图找出我们在使用大型表时遇到的性能问题。我们有一个自制的表格小部件,除其他外,它将列宽设置为标题宽度或行宽的最大值。

对于一个 10 行 x 500 列的表格,这可能需要将近 40 秒 (!),考虑到表格可以在一秒钟内呈现出来,这似乎太长了。

这是整个函数:

  var dataTable = this._div.find('.data-table');
  var headerTable = this._div.find('.data-header-table');
  if (dataTable.length === 0 || headerTable.length === 0) {
    return;
  }
  dataTable = dataTable[0];
  headerTable = headerTable[0];

  if (dataTable.rows.length === 0) {
    return;
  }

  var dataTr = dataTable.rows[0];
  var headerTr = headerTable.rows[headerTable.rows.length - 1];

  var marginColumnWidths =
    $(dataTr.cells[0]).outerWidth(true) +
    $(dataTr.cells[1]).outerWidth(true) +
    $(dataTr.cells[2]).outerWidth(true) -
    DOM.getHPaddings($(headerTr.cells[0])) + 1;

  $(headerTable)
    .find('> tbody > tr > td:first-child')
    .width('1%')
    .children()
      .first()
      .width(marginColumnWidths);

  for (var i = 1; i < headerTr.cells.length; i++) {
    var headerTd = $(headerTr.cells[i]);
    var dataTd = $(dataTr.cells[i + 2]);
    var commonWidth = Math.max(
      Math.min(headerTd.width(), 100),
      dataTd.width()
    );
    headerTd.width('1%').find('> div').width(commonWidth);
    dataTd.children().first().width(commonWidth);
  }

如果我替换

    var commonWidth = Math.max(
      Math.min(headerTd.width(), 100),
      dataTd.width()
    );

有一个常数

    var commonWidth = 100;

执行时间从 38 秒下降到不到 1 秒,这表明问题在于读取/计算当前宽度而不是设置新宽度。从我所做的分析/采样来看,jQuery 似乎花费了过多的时间来处理 CSS 计算。

谁能推荐一种更有效的方法来做到这一点?

编辑:

我已经尝试了 css("width") 和 outerWidth() ,但性能没有任何显着变化。我们使用的是 jQuery 1.7.2,但升级到 1.8.1 并没有显着改变性能。

【问题讨论】:

    标签: jquery performance


    【解决方案1】:

    使用.css("width") 而不是.width(),对.width() 方法进行了更改,使其执行速度变慢。阅读本文了解更多信息:http://blog.jquery.com/2012/08/16/jquery-1-8-box-sizing-width-csswidth-and-outerwidth/

    var commonWidth = Math.max(
      Math.min(parseFloat(headerTd.css("width")), 100),
      dataTd.width()
    );
    

    【讨论】:

    • 誓言。那篇博文让人大开眼界。必须订阅这些提要。谢谢! +1!
    • 嗯。测试了这个。与我建议的方法相比。看来差别不大。以下是测试:width one loopcss width one loopcss two loopswidth two loops。结果 - 几乎没有区别。最慢的 - width 一个循环。最快的 - css 之一。时不时不同。 注意: 四个不同的测试与 on case 因为看起来 js perf 不会清除测试用例之间的 html 状态。
    • 感谢您的建议。我应该提到我在 jQuery 1.7.2 中尝试了 css("width") ,但并没有更快。我刚刚用 1.8.1 重新测试,看看性能是否有所提高,但没有。
    【解决方案2】:

    据我所知 - .width() 采用实际宽度(并非总是在 css 中设置一组)并获得它 - 浏览器必须计算它(强制页面重绘和宽度计算本身)。现在,您正在设置宽度,浏览器需要重绘所有内容。它可能会稍有延迟,但在下一步中您将再次获取宽度 - 浏览器必须重绘页面以获得真正的宽度。首先计算宽度,然后 - 在另一个循环中,设置计算值。我认为这应该会有所帮助

    编辑

    Kelvin B 方法相比对此进行了测试。差异不显着。看起来最好的是使用 css("width") 时。以下是测试: 嗯。测试了这个。与我建议的方法相比。看来差别不大。这里是测试: width one loopcss width one loopcss two loopswidth two loops。结果 - 几乎没有区别。最慢的 - “宽度一个循环”。最快的 - 有css 的人之一。对我来说时不时地不同。

    注意: 四个不同的测试与 on case 因为看起来 js perf 不会清除测试用例之间的 html 状态。

    不确定在您的情况下可以做什么,但我觉得奇怪的是您正在使用.width('1%')。对我来说,您似乎不需要它,所以也许您可以尝试将其删除。

    【讨论】:

      【解决方案3】:

      如果你在非常大的表格的表格单元格(或标题)上执行 .width(以及 .css("width")),隐藏元素会花费大量时间!!!可见元素。原因是,如果元素是隐藏的,浏览器会很好而且高效,如果元素是可见的,浏览器并没有做出任何努力来找出宽度会是多少。但是,对于隐藏元素,jQuery 的 .width 显然会返回宽度(如果它是可见的),而不是仅仅返回零(它是隐藏的)。对于大表,这意味着浏览器必须再次呈现整个表。如果表真的很大,它可能需要一秒钟。如果您对多个隐藏列(仅测量它们的宽度)执行此操作,您的页面将变得毫无用处。

      所以除非你真的需要知道,否则不要测量隐藏元素的宽度。

      相关链接,重复我刚才所说的(以及更多):here

      【讨论】:

        猜你喜欢
        • 2010-12-15
        • 2013-04-05
        • 1970-01-01
        • 2013-01-17
        • 1970-01-01
        • 1970-01-01
        • 2010-09-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多