IE8(javascript):加载SELECT元素中的大型选项列表非常慢

时间:2012-03-09 19:15:51

标签: javascript internet-explorer-8

我正在使用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>

3 个答案:

答案 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。

使用Javascript:

$(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);
    }