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');
精彩评论