IE8 (javascript):在 SELECT 元素中加载大的选项列表非常慢
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9639703/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
IE8 (javascript): very slow to load large list of options in SELECT element
提问by Ross
I'm loading SELECT element with 6000 items using createElement and add methods. The code is shown below, and can also be accessed here. In IE8 it takes around 16 seconds to load the list and about the same time to clear it. In IE9 and Firefox the loading time is < 2 seconds and clearing time is < 1 second. Any ideas on how I can improve the speed in IE8?
我正在使用 createElement 和 add 方法加载具有 6000 个项目的 SELECT 元素。代码如下所示,也可以在这里访问。在 IE8 中,加载列表大约需要 16 秒,清除列表大约需要相同的时间。在 IE9 和 Firefox 中,加载时间 < 2 秒,清除时间 < 1 秒。关于如何提高 IE8 速度的任何想法?
Thank you.
谢谢你。
<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>
回答by pseudosavant
My guess is that that particular DOM operation is just really slow in IE8. In general, manipulating the DOM is the slowest type of operation in any browser. To get around that I typically try to find ways to combine my changes into one DOM update (e.g. add an HTML "batch" of 6000 rows to a table instead of individually adding 6000 rows to a table).
我的猜测是那个特定的 DOM 操作在 IE8 中真的很慢。一般来说,操作 DOM 是所有浏览器中最慢的操作类型。为了解决这个问题,我通常会尝试找到将我的更改合并到一个 DOM 更新中的方法(例如,将 6000 行的 HTML“批处理”添加到表中,而不是单独向表中添加 6000 行)。
In this example the only way to do that would probably be to create all of the <option>
elements as HTML and then use innerHTML
to insert them into the <select>
. See this jsfiddle example: http://jsfiddle.net/pseudosavant/bVAFF/
在此示例中,唯一的方法可能是将所有<option>
元素创建为 HTML,然后innerHTML
将它们插入到<select>
. 请参阅此 jsfiddle 示例:http: //jsfiddle.net/pseudosavant/bVAFF/
I don't have IE8 to test with, but it is muchfaster even in Firefox (22ms vs 500ms) for me.
我没有IE8与测试,但它是很多,甚至在Firefox更快(22毫秒VS 500毫秒),对我来说。
Update
更新
Looks like it didn't work with innerHTML
in IE for loading the list, but it did work for clearing it. Loading it works using jQuery $(o).html(html);
though. I updated the jsfiddle example and it works in IE9, and hopefully IE8 now.
看起来它innerHTML
在 IE 中无法用于加载列表,但它确实可以用于清除列表。加载它$(o).html(html);
虽然使用 jQuery 工作。我更新了 jsfiddle 示例,它可以在 IE9 中运行,希望现在可以在 IE8 中运行。
Javascript:
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;
}
回答by mbokil
If you are supporting IE7/IE8 you should minimize JavaScript manipulation of the DOM. So if you are appending, inserting or deleting nodes you need to minimize DOM manipulation in general. The best solution is to bulk update items.
如果您支持 IE7/IE8,您应该尽量减少对 DOM 的 JavaScript 操作。因此,如果您要追加、插入或删除节点,则通常需要尽量减少对 DOM 的操作。最好的解决方案是批量更新项目。
So, if you have a select list and you are doing JQuery.append() you will get better performance if you concatenate your entire options string before appending.
因此,如果您有一个选择列表并且您正在执行 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);
Additionally, if you want to see how slowly JavaScript is executed by IE8 run the SunSpider JS test. Firefox 22 and Chrome 27 are around 300 ms while IE8 is around 4,000 ms. That tells a lot about why your JS speeds are slow. Interestingly IE10 comes in at less than 200 ms now. http://www.webkit.org/perf/sunspider/sunspider.html
此外,如果您想查看 IE8 执行 JavaScript 的速度有多慢,请运行 SunSpider JS 测试。Firefox 22 和 Chrome 27 约为 300 毫秒,而 IE8 约为 4,000 毫秒。这说明了为什么你的 JS 速度很慢。有趣的是 IE10 现在不到 200 毫秒。http://www.webkit.org/perf/sunspider/sunspider.html
回答by Jahaziel
I had a very similar situation.
我有一个非常相似的情况。
I have a set of inputs with 1700+ so I provided a "filter" option that would copy the select and apply a filter based on a besides the copied list. (It "opens" a dialog that expands the dropdownlistbox to a list almost as big as 80% of the screen)
我有一组 1700+ 的输入,所以我提供了一个“过滤器”选项,该选项将复制选择并基于复制列表之外的 a 应用过滤器。(它“打开”一个对话框,将下拉列表框扩展到几乎与屏幕 80% 一样大的列表)
Copying the worked unnoticeably in other browsers but took 8-15 secs in IE.
在其他浏览器中复制工作并不明显,但在 IE 中需要 8-15 秒。
The solution, based on previous answers, and also based on this post (Learn the slow (and fast) way to append elements to the DOM) was to add all the items to a HTL string, then assigning this to the innerHTML of a new object, one that is not yet part of the DOM. And finally, replacing the object from the DOM with the new one.
解决方案,基于以前的答案,也基于这篇文章(Learn the slow (and fast) way to append elements to the DOM)是将所有项目添加到 HTL 字符串,然后将其分配给新的 innerHTML对象,还不是 DOM 的一部分。最后,用新的对象替换 DOM 中的对象。
This apparently reduces the number of "reflow" operations performed by the browser, which is most likely the culprit of such slow performance.
这显然减少了浏览器执行的“重排”操作的数量,这很可能是导致性能下降的罪魁祸首。
Some of the test before implementing this style, was to run the full for loop without adding the options to the list, and in such test, the code executed very fast, it was clear that selectElement.add(optionElement) was the slow part.
在实现这种风格之前的一些测试是运行完整的 for 循环而不将选项添加到列表中,并且在这样的测试中,代码执行得非常快,很明显 selectElement.add(optionElement) 是缓慢的部分。
Here is an example of what my function ended like:
这是我的函数结束的示例:
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);
}