Javascript Table.append()同时发生

Javascript Table.append()同时发生,javascript,jquery,Javascript,Jquery,我有一个for循环,在这个循环中,我将行附加到表中。虽然我在循环中一次附加一个tr,但在循环完成之前,浏览器不会渲染其中任何一个 起初,我认为可能是浏览器渲染速度太快,我没有注意到,但在将行数增加到(比如)10000行后,速度明显减慢,然后整个表立即显示出来 链接: 递增计数器以增加行数 此外,如果您将计数器更改为3(或另一个小数字),并取消对警报()的注释,它将暂停循环,并显示每一行一次添加一行 HTML: <div></div> var table = $('<

我有一个
for
循环,在这个循环中,我将行附加到
表中。虽然我在循环中一次附加一个
tr
,但在循环完成之前,浏览器不会渲染其中任何一个

起初,我认为可能是浏览器渲染速度太快,我没有注意到,但在将行数增加到(比如)10000行后,速度明显减慢,然后整个表立即显示出来

链接:

递增
计数器
以增加行数

此外,如果您将
计数器
更改为3(或另一个小数字),并取消对
警报()的注释,它将暂停循环,并显示每一行一次添加一行

HTML:

<div></div>
var table = $('<table />').appendTo($('div'));
var counter = 1000;
var html = [];
var j = 0;

for (var i = 1 ; i < (counter + 1) ; i++) {
    html[j++] = '<tr>';
    html[j++] =    '<td>'+i+'-1</td><td>'+i+'-2</td><td>'+i+'-3</td>';
    html[j++] = '<tr>';
    table.append(html.join(''));
    //alert('pause');
    html = [];
    j = 0;
}
    table td {
    padding: 3px;
    border: 1px solid red;
}

注意:

<div></div>
var table = $('<table />').appendTo($('div'));
var counter = 1000;
var html = [];
var j = 0;

for (var i = 1 ; i < (counter + 1) ; i++) {
    html[j++] = '<tr>';
    html[j++] =    '<td>'+i+'-1</td><td>'+i+'-2</td><td>'+i+'-3</td>';
    html[j++] = '<tr>';
    table.append(html.join(''));
    //alert('pause');
    html = [];
    j = 0;
}
    table td {
    padding: 3px;
    border: 1px solid red;
}
我找到了一种方法来强制循环减速,允许一次添加一行

链接:

var html='';
var numbertorun=15;
无功延迟=500;
(函数循环(i){
setTimeout(函数(){
html=''+i+'-1'+i+'-2';
$('table').append(html);
如果(--i)循环(i);
},延误)
})(数字运行);


因此,我想我的问题不是如何做到这一点,而是为什么不在原始
for
循环中一次插入一行。

我想理解这个问题需要一些背景知识

每次向网页中的表添加新行时,脚本都会改变浏览器内存中文档的模型。用于此目的的API称为DOM(文档对象模型)


对DOM的单独更新并不总是意味着页面将被重新绘制。当一组给定的DOM更改将导致浏览器重新呈现页面时,由浏览器决定

事实上我不知道,但我猜浏览器通常每秒更新视图大约40-60次。问题是:如果表格打印所需时间少于1/60秒,则无法看到部分更新

通过添加计时器,当然可以减慢创建表的进度。正如您所看到的,这将允许您在for循环期间的不同点上看到重新绘制的页面

如果您希望强制浏览器重新绘制UI,可以尝试应用一些JavaScript攻击。例如,一个这样的黑客记录在

如果您慎重地希望缓慢地运行程序并缓慢地添加行,比如说每秒添加一行,同时可能使用JavaScript执行其他操作,那么您需要以某种方式触发新的迭代或使用另一个(JavaScript)线程来运行循环

使用
setTimeout
减慢打印速度的示意图示例(每秒打印1行,只需在
窗口中调整第二个参数。setTimeout
更改延迟):

var table=$('').appendTo($('div');
var i=0;
var计数器=1000;
函数addRow(){
表.追加(''+i+'-1'+i+'-2'+i+'-3');
i++;

如果(ijQuery append方法类似于javascript appendChild方法。这两种方法都会遍历DOM并在父节点的末尾插入元素。此任务需要时间,在循环中执行此操作将导致DOM结构频繁更改,而DOM将无法复制。因此,使用settimeout插入行让浏览器有足够的时间重新加载内容。因此,您可以在第二种方法中逐个插入行。

每次向页面添加元素时,浏览器都需要重新绘制整个页面。就呈现而言,这是一个非常密集的过程,而且非常缓慢。因此,如果您一点一点地进行小的更改,则I’我将使页面显示得非常慢。浏览器所做的是将小的更改分组为大的更改。最终结果是页面将以更快的速度聚合呈现

浏览器正在执行以下操作:


这些循环或计算是在一瞬间完成的,因此您将无法“看到”正在绘制的表格。今天的计算机电源,是吗?编辑:此外,您应该尽可能快地绘制表格,而不是从计算机中提取所有电源(耗尽ram)。相反,如果您想要这种效果,只能使用延迟(就像你上一个例子一样)。我只是在这里猜测,但我认为浏览器在JS线程繁忙时不会呈现任何内容。这不是一个非常常见的问题,但却是一个非常烦人的问题。感谢您提供了深入的示例和说明“由浏览器决定,当给定的DOM更改集将导致浏览器重新呈现页面时。”绝对迷人。这基本上就是我想要的答案。