1

我的应用程序有一长串对象,其宽度需要通过 jQuery 进行修改。目前我正在使用这样的代码:

$('#my_list div.text_field').each(function() {
  // Cache objects we're going to use multiple times.
  var $textField = $(this);
  var $listContents = $textField.closest('div.list_contents');

  // Find widths.
  var contentsWidth = $listContents.outerWidth();
  var avatarsWidth = $listContents.find('div.avatars').outerWidth();
  var tagsWidth = $listContents.find('div.tags').outerWidth();
  var textLeft = $textField.position().left;

  // Update the width.
  var newTextWidth = contentsWidth - textLeft - avatarsWidth - tagsWidth;
  $textField.css({ width: newTextWidth });
});

但是,当有数百个对象需要操作时,需要一段时间(> 1 秒)。知道如何使这更快吗?我应该完全避开 jQuery 并使用原生 JS 吗?

4

2 回答 2

4

好的,通过一系列改进,我能够将运行此代码(在 Chrome 18 上的一系列约 600 个项目上)所需的时间从 3000 多毫秒缩短到 70 毫秒。

最大的改进来自在原始 HTML 元素上使用 offsetWidth 而不是 jQuery 的 outerWidth() 语句。仅此一项就减少了 50% 以上的时间:

avatarsWidth = $listContents.find('div.avatars')[0].offsetWidth;

第二个最剧烈的变化来自于减少我所做的 DOM 修改的数量。在上面的代码中,我循环遍历元素,计算它们的宽度,然后立即将这些宽度应用到 DOM。在我改进的代码中,我仍然循环计算宽度,但是我存储这些宽度,从 DOM 中分离元素,应用存储的宽度,然后重新附加它们。感谢@muffel 提出这个想法。这节省了总时间的 30% 以上:

$('#my_list div.text_field').each(function() {
  var $textField = $(this);
  // ...
  var newTextWidth = contentsWidth - textLeft - avatarsWidth - tagsWidth;
  $textField.attr('data-width', newTextWidth);
});

$('#my_list')
  .detach()
  .find('div.text_field')
    .each(function() {
      $(this).css({ width: $(this).attr('data-width') });
    })
    .end()
  .appendTo('#container');

第三大改进来自于减少遍历 DOM 的次数。我不是每次通过循环都选择元素,而是预先选择它们,然后引用循环内的索引。这构成了其余改进的大部分:

var $avatars = $('#my_list .avatars');
// ...
$('#my_list div.text_field').each(function(i) {
  // ...
  avatarsWidth = $avatars.eq(i).offsetWidth;
  // ...
});

希望这对某人有帮助!

于 2012-04-27T02:57:11.877 回答
0

对于初学者来说,你不应该用 $(this) 把它包起来......除非我错过了一些东西(我可能是)你应该能够在每个 $textfield 上下文中使用“this”......这将为你节省函数调用和 var 创建。还将 var 声明移出函数......这也将节省更多周期。让我知道这是否会加快速度。

于 2012-04-26T23:18:59.867 回答