jQuery.addClass()行为,一次全部

时间:2010-08-09 19:38:15

标签: jquery performance

我有这个简单的jQuery调用来突出显示一堆元素(几千个):

jQuery(elem).addClass('highlighted');

浏览器的作用是快速添加类,但不重新绘制元素。有没有办法在我添加类时立即呈现每个“突出显示”元素。现在,用户看到了一个口吃,直到我添加类的循环结束。


编辑:

更多代码:

var elem = findNext(); // walks the dom and finds next search match. ~10ms each call
while(elem){
   highlight(elem);
   elem = findNext(); 
}

function highlight(elem){   
   jQuery(elem).addClass('highlight');
   ...
}

4 个答案:

答案 0 :(得分:3)

这是因为只要JavaScript函数正在运行,就不会呈现DOM更改。用户界面代码是单线程的,浏览器在执行时会锁定。通常这不是问题,因为JS非常快并且函数运行时间不长。但如果他们这样做,你就会看到缓慢的行为。

您的功能需要在其工作中停止,以使浏览器有机会再次响应。您可以使用setTimeout()并记住上次停止的位置来解决此问题。

这应该会给你一个想法:

// prepares a closure function to handle affected elements in chunks of n
function updatePartial(elems, chunksize) {
  var current = 0;
  return function() {
    // changes n elements in a loop
    for (var i=0; i<chunksize; i++) {
      jQuery(elems[current+i]).addClass('highlighted');
    }
    current += chunksize;
    // calls itself again after a short break
    if (current < elems.length) setTimeout(arguments.callee, 10);
  }
}

// aquire and execute the closure function
updatePartial(jQuery("selector").get(), 100)();

(经http://jsfiddle.net/fPdAg/测试)

闭包是一种避免在其他实现中需要的全局变量的优雅方法。


编辑:以上的通用版本是:

// prepares a closure function to handle affected elements in chunks of n
function updatePartial(elems, chunksize, payload) {
  var current = 0;
  return function() {
    // changes n elements in a loop
    for (var i=0; i<chunksize; i++) {
      // apply the payload function to current element
      payload.apply(elems[current+i]);
    }
    current += chunksize;
    // calls itself again after a short break
    if (current < elems.length) setTimeout(arguments.callee, 10);
  }
}

// aquire and execute the closure function, supply custom payload function
updatePartial(jQuery("selector").get(), 100, function() {
  jQuery(this).addClass('highlighted');
})();

答案 1 :(得分:1)

我认为原因是因为浏览器行为,而不是JQuery问题。 致电时

jQuery(elem).addClass('highlighted');

Javascript runnig时,浏览器会停止工作,直到JS完成执行。所以浏览器不会重新发布任何东西,直到JQuery addClass到每个元素 试试这个技巧

<script>
x = jQuery(elem).size();
y = number_item_each_time;
z = time_by_micro;
start = 0;
t = setInterval(function(){
      $(elem).slice(start, start + y).addClass('highlighted');
      start = start + y;
      if(start > x)
          clearInterval(t);
  }, z);
</script>

答案 2 :(得分:0)

您确定浏览器正在快速添加课程吗?听起来这需要相当长的时间来完成操作,这正是我所期望的。

您可以尝试将addClass()调用批处理为一系列setTimeout回调(例如,每次执行100个元素的10个调用)以更快地显示结果。

<强>更新

我刚注意到你说“直到我添加课程的循环完成”。您是否只对addClass进行一次调用,或者为for循环中的每个元素单独调用它?

你绝对应该拨打一个电话jQuery('.all-your-elements').addClass('highlighted')。它会更具可读性和更快。

答案 3 :(得分:0)

仅使用jQuery 1.4.2检查解决方案(不带setTimeout) 它使用$(document)上的队列来推迟函数执行 并按顺序执行它们。

http://jsfiddle.net/xXGz3/

  $(function() {
      $('.highlight').each(function() {
          var e = $(this);
          $(document).delay(1000).queue(function(next) {
              e.addClass('a');
              next();
          });
      });
  });