Jquery selectors by CSS class in IE is really slow--workarounds?
I have a web app where I have several elements with class="classA"
. I want to select and apply a function to all of them. I am doing the obvious thing, which is $(".classA").each(function () { ... })
. This works just fine in Chrome/Safari/Firefox but is really slow in IE. It turns ou开发者_如何转开发t IE has serious performance issues when selecting things by CSS class in jQuery.
I was wondering if anyone has suggestions on good ways to deal with this. I can't use ID selectors because there can be multiple DOM elements I want to select.
-- EDIT --
Below is my tests code.
test1 uses
document.getElementById("id")
and is very fast.test2 uses
$("#id")
and is pretty slow.test3 uses
$(".class")
and is even slower.
As far as I can tell, there is no native implementation of document.getElementsByClassName in IE8--I get an error when I try to use it.
<html>
<head>
<script type="text/javascript" src="jquery-1.4.2.js"></script>
<script type="text/javascript">
function test1 ()
{
var start = (new Date).getTime();
for (var i = 0; i < 10000; i++)
{
document.getElementById("test1");
}
var elapsed = (new Date).getTime() - start;
alert("test1 elapsed: " + elapsed);
}
function test2 ()
{
var start = (new Date).getTime();
for (var i = 0; i < 10000; i++)
{
var x = $("#test2");
}
var elapsed = (new Date).getTime() - start;
alert("test2 elapsed: " + elapsed);
}
function test3 ()
{
var start = (new Date).getTime();
for (var i = 0; i < 10000; i++)
{
$(".test3");
}
var elapsed = (new Date).getTime() - start;
alert("test3 elapsed: " + elapsed);
}
</script>
</head>
<body>
<div id="test1">test1</div>
<div id="test2">test2</div>
<div id="test3" class="test3">test3 1</div>
<div id="test3" class="test3">test3 2</div>
<div id="test3" class="test3">test3 3</div>
<div id="test3" class="test3">test3 4</div>
<input type="button" onclick="test1();" value="test1" />
<input type="button" onclick="test2();" value="test2" />
<input type="button" onclick="test3();" value="test3" />
</body>
</html>
Have a look at jQuery: Performance analysis of selectors:
Test 2 - Finding an element by Class
Although CSS classes are intended to be reused among elements, you might create some elements with a unique class name just to identify and retrieve them through javascript. This is exactly what we test in this second test by seaching the element whose class is "p-4781". We have four alternatives:
A - Using the class selector
$('.p-4781').html()
B - Using the class selector + tag
$('p.p-4781').html()
C - Using attribute search + tag
$('p[class="p-4781"]').html()
D - Using tag search + filter
$('p').filter('.p-4781').html()
After running this test for the first time in different browsers, I got:
Firefox Opera IE6 IE7 Safari A 2891 641 1718 631 329 B 453 78 313 180 78 C 422 109 578 201 187 D 203 266 375 210 94
The table above shows case B as the fastest selector for most browsers (except Firefox). It is easy to understand why case A isn't efficient, since the code has to iterate over all elements of the DOM tree. Case C and D aren't that bad, but I would say case B should be the preferred one for this goal.
So use a tag name plus class name. It's way faster in older browsers.
You can try a variety of things, but IE is optimized to fetch elements by ID, nothing else (it puts elements IDs in a hashtable under the covers).
If you're generating your page via some server-side technology, you could determine the list of elements and then output a JavaScript array of the IDs of those elements, then when the page loads you could loop through that array and collect your elements by ID.
That's the approach we've taken with ASP.NET apps with good success, though you may be doing something else. I would at least investigate the options jmbledsoe has described, they can help a little, but I doubt you'll get the performance you're hoping for.
I don't know if this will help, but if your elements are all the same tag (e.g. DIV) you could use a selector like "DIV.classA". jQuery may be able to optimize that with a call to getElementsByTagName.
If you can specify a parent element, e.g. $('DIV.classA', someParent), that would limit the scope of what's being searched, which may increase performance.
精彩评论