Производительность метода jQuery width()

Я - нуб JQuery, пытающийся отследить проблему производительности, которую мы имеем с большими таблицами. У нас есть домашний виджет таблицы, который, помимо прочего, устанавливает ширину столбцов на максимум ширины заголовка или ширины строк.

С таблицей из 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"), так и externalWidth() без каких-либо существенных изменений в производительности. Мы использовали jQuery 1.7.2, но обновление до 1.8.1 существенно не изменило производительность.

3 ответа

Использование .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()
);

Насколько я знаю - .width() принимает реальную ширину (не всегда один набор в css) и для ее получения - браузер должен вычислить ее (принудительное перерисовывание страницы и сам расчет ширины). Теперь вы устанавливаете ширину, браузер должен перерисовать все. Это может сделать это с небольшой задержкой, но на следующем шаге вы снова берете ширину - браузер ДОЛЖЕН перерисовать страницу, чтобы получить реальную ширину. Сначала посчитайте ширину, затем - в другом цикле, установите рассчитанные значения. Я думаю, что это должно помочь

РЕДАКТИРОВАТЬ:

Протестировано это по сравнению с подходом Kevin B. Разница не значительна. Похоже, лучше всего, когда используется CSS ("ширина"). Вот тесты: Хм. Проверял это. Сравнивая с подходом я предложил. Оказалось, что разница не большая. Вот тест: ширина одной петли, css ширина одной петли, css две петли, ширина две петли. В результате - почти без разницы. Самый медленный - "ширина одной петли". Самый быстрый - один из тех, у кого css, Разное время от времени для меня.

Примечание: четыре разных теста с on case выглядят так, как будто js perf не очищает состояние html между тестовыми случаями.

Не уверен, что можно сделать в вашем случае, но то, что я вижу странно, .width('1%') ты используешь. Для меня это выглядит так, как будто вам это не нужно, так что, возможно, вы можете попробовать удалить его.

Если вы используете.width (а также.css("width")) для ячейки таблицы (или заголовков) очень больших таблиц, это займет очень много времени для скрытых элементов!!! и очень быстро для видимых элементов. Причина в том, что если элемент скрыт, браузер, будучи красивым и эффективным, не приложил никаких усилий, чтобы выяснить, какой была бы ширина, если бы элемент был виден. Но jQuery.width, по-видимому, для скрытых элементов, возвращает, какой была бы ширина, если бы она была видимой, вместо того, чтобы просто возвращать ноль (это скрыто в порядке). Для больших таблиц это означает, что браузер должен визуализировать всю таблицу снова. Если стол действительно большой, это может занять секунду. И если вы сделаете это для нескольких скрытых столбцов (просто измеряя их ширину), ваша страница станет бесполезной.

так что не измеряйте ширину скрытых элементов, если вам не нужно ДЕЙСТВИТЕЛЬНО знать.

соответствующая ссылка, повторяя то, что я только что сказал (и более): здесь

Другие вопросы по тегам