我正在使用createElement和添加方法加载带有6000个项目的SELECT元素。代码如下所示,也可以访问here。在IE8中,加载列表大约需要16秒,大约在同一时间清除它。在IE9和Firefox中,加载时间是<1。 2秒和清除时间是&lt; 1秒。关于如何提高IE8速度的任何想法?
谢谢。
<script type="text/javascript">
window.onload = loadList;
function loadList() {
clearList();
var start = new Date().getTime();
var o = document.getElementById("listLookupAvailableItems")
for (var i = 0; i < 6000; i++) {
var option = document.createElement("option");
option.text = 'ABCDF ' + i;
option.value = option.text;
o.add(option, o.options[null]);
}
log('Load time: ' + (new Date().getTime() - start));
}
function clearList() {
var start = new Date().getTime();
document.getElementById("listLookupAvailableItems").options.length = 0;
log('Clear time: ' + (new Date().getTime() - start));
return false;
}
function log(txt) {
document.getElementById('infoPanel').innerHTML += '</br>' + txt;
}
</script>
答案 0 :(得分:9)
我的猜测是IE8中特定的DOM操作真的很慢。通常,操纵DOM是任何浏览器中最慢的操作类型。为了解决这个问题,我通常会尝试将我的更改组合到一个DOM更新中(例如,将6000行的HTML“批处理”添加到表中,而不是单独向表中添加6000行)。
在此示例中,唯一的方法可能是将所有<option>
元素创建为HTML,然后使用innerHTML
将它们插入<select>
。请参阅此jsfiddle示例:http://jsfiddle.net/pseudosavant/bVAFF/
我没有使用IE8进行测试,但即使在Firefox(22ms vs 500ms)中,它也很多更快。
看起来它在IE中用innerHTML
无法加载列表,但它确实可以清除它。加载它可以使用jQuery $(o).html(html);
。我更新了jsfiddle示例,它在IE9中工作,现在希望IE8。
$(document).ready(function(){
loadListBatch();
});
function loadListBatch() {
clearListBatch();
var start = new Date().getTime();
var o = document.getElementById("listLookupAvailableItems")
var html = "";
for (var i = 0; i < 6000; i++) {
html += "<option value='"+'XYZ' + i+"'>"+'XYZ ' + i+"</option>";
}
// o.innerHTML = html; // Only one DOM operation, but still doesn't work in IE
$(o).html(html); // Using jQuery to insert the HTML makes it work with IE
console.log('Load time: ' + (new Date().getTime() - start));
}
function clearListBatch() {
var start = new Date().getTime();
document.getElementById("listLookupAvailableItems").innerHTML = ""; // It was already only one DOM call, but this is faster it seems.
console.log('Clear time: ' + (new Date().getTime() - start));
return false;
}
答案 1 :(得分:2)
如果您支持IE7 / IE8,则应尽量减少对DOM的JavaScript操作。因此,如果要追加,插入或删除节点,则需要最小化DOM操作。最佳解决方案是批量更新项目。
所以,如果你有一个选择列表并且你正在使用JQuery.append(),那么如果在追加之前连接整个选项字符串,你将获得更好的性能。
var str = $('<option value="x">Item 1</option>' + '<option value="y">Item 2</option>');
$('#selectMenu').append(str);
//or in a loop
var array = ['orange','apple','grapes','mangoes'];
var str = '';
for (var x= 0; x < array.length; x++) {
str = str + '<option value="' + x + '">' + x + '</option>';
}
$('#selectMenu').append(str);
此外,如果您想了解IE8执行JavaScript的速度有多慢,请运行SunSpider JS测试。 Firefox 22和Chrome 27大约为300毫秒,而IE8大约为4,000毫秒。这说明了为什么你的JS速度很慢。有趣的是IE10现在不到200毫秒。 http://www.webkit.org/perf/sunspider/sunspider.html
答案 2 :(得分:0)
我有一个非常相似的情况。
我有一组1700+的输入,因此我提供了一个“过滤器”选项,该选项将复制选择内容并根据复制的列表之外的内容应用过滤器。 (它“打开”一个对话框,将下拉列表框扩展到几乎与屏幕的80%一样大的列表)
在其他浏览器中复制作品的效果不明显,但在IE中花费了8-15秒。
基于先前的答案以及本文(Learn the slow (and fast) way to append elements to the DOM)的解决方案是将所有项目添加到HTL字符串中,然后将其分配给新对象的innerHTML,而不是仍是DOM的一部分。最后,用新对象替换DOM中的对象。
这显然减少了浏览器执行的“重排”操作的数量,这很可能是这种缓慢性能的元凶。
在实现这种样式之前,有些测试是运行full for循环而不在列表中添加选项,在这种测试中,代码执行得非常快,很明显selectElement.add(optionElement)是较慢的部分。
以下是我的函数结束的示例:
function fillselector(IdSelect){
var selector = document.getElementById(IdSelect);
if( !selector ){
alert('Original select element not found.');
return;
}
var lista = document.getElementById('selectFilter_lista');
if( !lista ){
alert('Copied list element not found.');
return;
}
var filterText = noSpecialChars(document.getElementById('selectFilter_text').value);
var options =''
for (var i = 0; i < selector.length; i++){
if (filterText == '' || noSpecialChars(selector[i].text).indexOf(filterText) != -1 ){
//Commented code works but is painfuly slow on IE
//var option = document.createElement("option");
//option.value = selector[i].value;
//option.text = selector[i].text;
//lista.add(option);
options += '<option value="'+selector[i].value+'">'+selector[i].text+'</option>';
}
}
var newList = document.createElement('select');
newList.id='selectFilter_list';
newList.className='selectFilter_list';
newList.size = 20;
newList.ondblclick= function(){closeselector(IdSelect, true);}
newList.innerHTML = options;
newList.value = selector.value;
var listParent = lista.parentElement; //<div> that only contains the <select>
listParent.removeChild(lista);
listParent.appendChild(newList);
}