我的页面中有大约9000个元素,必须经常重建,这可能需要几秒钟。
所以,我制作了一个覆盖元素的小窗口小部件Loading..
。信息。在我重建元素之前,我调用showOverlay()
,然后在循环之后调用hideOverlay()
。
但是在显示Loading...
消息之前,循环会锁定页面,因此它永远不会出现。
function rebuild() {
showOverlay(); // The overlay never appears...
for (var i=0;i<9000;i++) {
// append element...
}
hideOverlay();
}
如何在开始循环之前等待渲染叠加?
答案 0 :(得分:4)
function do_rebuild() {
for (var i=0;i<9000;i++) {
// append element...
}
hideOverlay();
}
function rebuild() {
showOverlay(); // The overlay will appear
window.setTimeout('do_rebuild();',1);
}
是我所知道的唯一跨浏览器方式。
答案 1 :(得分:1)
您需要将循环置于设置超时内,以便它不会占用页面。即使您的叠加显示,也没有人喜欢他们的页面冻结
var counter = 0;
function rebuild() {
showOverlay();
doWork();
}
function doWork() {
if(counter < 9000){
// append element
counter++;
setTimeout(function(){
doWork();
},10);
}
else {
hideOverlay();
}
}
编辑:这个答案实际上会花费更长时间来处理页面。在90秒范围内某处是非常不可接受的,另一种选择可能是每100次迭代设置一次超时,这将使总加载时间增加约1秒,但应该阻止页面冻结。
function doWork() {
if(counter < 9000){
// append element
if(counter % 100 == 0) {
setTimeout(function(){
doWork();
},10);
counter++;
}
else {
doWork();
counter++;
}
}
else {
hideOverlay();
}
}
答案 2 :(得分:0)
其他答案显示了如何使用计时器以“伪线程”方式执行此操作。
与此同时,我了解了Web Workers,这是一个将脚本执行与DOM更新分开的线程解决方案。
WebKit和Firefox目前支持它们,并计划为IE 10提供支持。
答案 3 :(得分:0)
var loopCount = 0,
build = function() {
var frgm = document.createDocumentFragment();
for (var i = 0; i < 200 && loopCount < 9000; i++) {
// some codes
frgm.appendChild(someElement);
loopCount ++;
}
parentNode.appendChild(frgm);
if (loopCount < 9000) {
setTimeout(build, 10);
}
};
function rebuild() {
showOverlay(); // The overlay never appears...
build();
hideOverlay();
}