开发者

jQuery draws to a halt on Chrome and mac OS

Check out this fiddle: http://jsfiddle.net/mattball/nWWSa/

var $lis = $('ul.innerfade > li');

function fadeThemOut()
{
    $开发者_如何学JAVAlis.fadeOut('slow', fadeThemIn);
}

function fadeThemIn()
{
    $lis.fadeIn('slow', fadeThemOut);
}

// kick it off
fadeThemOut();

The fading in/out works fine a couple of times, but then starts going very slow. What is the problem? Is this a bug?


The problem is that the callbacks are executed for each element once it is faded in/out, not only when all of them are. So this accumulates a lot of callbacks. It goes like this (lets say we have only two elements, A and B):

At the beginning, the queues are empty:
A: []
B: []

Then you call fadeOut on both elements:
A: [fadeOut]
B: [fadeOut]

A fades out: fadeIn is added to both elements.
A: [fadeIn]
B: [fadeOut, fadeIn]

Then B fades out: Again, fadeIn is added to both elements.
A: [fadeIn, fadeIn]
B: [fadeIn, fadeIn]

A fades in: fadeOut is added to both elements.
A: [fadeIn, fadeOut]
B: [fadeIn, fadeIn, fadeOut]

B fades in: ...
A: [fadeIn, fadeOut, fadeOut]
B: [fadeIn, fadeOut, fadeOut]

And so forth. The exact order might differ, but as animations are queued by default, this adds more and more callbacks to the queue.

You can solve this using deferred objects:

$.when($lis.fadeOut('slow')).then(fadeThemIn);

DEMO

Now, fadeThemIn is only called when the animation of all elements is completed.


Another way would be to change the functions to not work on all elements, but only on the current one:

var $lis = $('ul.innerfade > li');

function fadeThemOut()
{
    $(this).fadeOut('slow', fadeThemIn);
}

function fadeThemIn()
{
    $(this).fadeIn('slow', fadeThemOut);
}

// kick it off
fadeThemOut.call($lis);

though it could be that the elements are not in sync then.

DEMO

In your specific case, you could just fade in and out the ul element.


Your code is EXTREMELY ineffective. It basically calls fadeout on all the elements, and then calls fadein on all elements, one time for each element, etc etc. This essentially creates a forkbomb, and before long the function is running millions of times in memory, since the amount of calls quadruples every time.

Here's a more effective way of doing it: http://jsfiddle.net/bVj3X/


First up, I would suggest that if you were trying to do this, do it on as little elements as possible. The more elements you perform this on, the more browser redraws happen. Currently, your fiddle is doing this on 4 elements, try doing it on 1 element. This way, your browser will be calculating one redraw at a time, instead of 4 (semi-)concurrently.

Change your $lis variable to:

var $lis = $('ul.innerfade');

Demo

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜