jQuery width()方法的性能

时间:2012-09-13 20:18:52

标签: jquery performance

我是一个jQuery noob试图追踪我们对大表的性能问题。我们有一个自制的表格小部件,除其他外,它将列宽设置为标题宽度或行宽的最大值。

使用10行乘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秒下降到不到一秒,表明问题在于读取/计算当前宽度而不是设置新宽度。从我所做的分析/抽样看来,似乎jQuery花费了大量的时间搞乱CSS计算。

有人可以推荐一种更有效的方法吗?

编辑:

我尝试过css(“width”)和outerWidth(),但性能没有任何重大变化。我们使用的是jQuery 1.7.2,但升级到1.8.1并没有显着改变性能。

3 个答案:

答案 0 :(得分:9)

使用.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 :(得分: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%')。对我来说,看起来你不需要它,所以也许你可以尝试删除它。

答案 2 :(得分:1)

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

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

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