使用JavaScript无阻塞地附加DOM元素
我想用异步JavaScript追加2000个表行。这需要大约3秒钟的时间,所有的UI控件都被阻塞在页面内。我可以在没有阻塞的情况下附加到DOM吗 如您所见,演示中的复选框仅在3-4秒后才能单击: 演示中包含的内容:使用JavaScript无阻塞地附加DOM元素,javascript,dom,Javascript,Dom,我想用异步JavaScript追加2000个表行。这需要大约3秒钟的时间,所有的UI控件都被阻塞在页面内。我可以在没有阻塞的情况下附加到DOM吗 如您所见,演示中的复选框仅在3-4秒后才能单击: 演示中包含的内容: function populateTable() { for (var i = 0; i < 4*1000; i++) { var tr = $('<tr></tr>'); ... tr.appendTo(table);
function populateTable() {
for (var i = 0; i < 4*1000; i++) {
var tr = $('<tr></tr>');
...
tr.appendTo(table);
}
}
setTimeout(populateTable, 0); // async
函数populateTable(){
对于(变量i=0;i<4*1000;i++){
var tr=$('');
...
tr.appendTo(表);
}
}
setTimeout(populateTable,0);//异步的
其思想是将表分块填充,然后让UI在块之间更新。这允许用户与复选框交互并查看表格填充情况,而不是盯着一个没有响应的UI的空白页面
您可以修改变量以找到可接受的用户体验。这个答案使用,如果你不熟悉它们,我建议你学习,因为它非常有用。这里的权衡是,填充表需要更长的时间,但这是值得的
编辑:我建议将表构建为一个字符串,并且只插入一次,因为它很快,就像其他答案一样。然而,这种异步“块”加载方法是一种很好的模式
var t1 = new Date().getTime();
var log = console.log;
var table = $('#the-table');
var rows = 4000
var columns = 10
var chunk = 100
var timeout = 50
async function populateTable() {
let totalRows = rows
while(totalRows > 0){
await addChunk()
totalRows -= chunk
}
log('table populated at ', (new Date().getTime() - t1), 'ms');
}
function addChunk(){
return new Promise(resolve=>{
setTimeout(()=>{
for (var i = 0; i < chunk; i++) {
var tr = $('<tr></tr>');
for (var j = 0; j < columns; j++) {
var td = $('<td></td>');
td.text('' + i + '_' + j);
td.appendTo(tr);
}
tr.appendTo(table);
resolve()
}
},timeout)
})
}
setTimeout(populateTable, 0);
var t1=new Date().getTime();
var log=console.log;
变量表=$(“#表”);
var行数=4000
变量列=10
var chunk=100
变量超时=50
异步函数populateTable(){
让totalRows=行
而(总计行数>0){
等待addChunk()
totalRows-=块
}
日志('表填充在',(new Date().getTime()-t1),'ms');
}
函数addChunk(){
返回新承诺(解决=>{
设置超时(()=>{
对于(var i=0;i
首先使用vanilla JS(更快),一次插入HTML,而不是将每一行、td和文本分别插入数千次:
const t1 = new Date().getTime();
const log = console.log;
const table = document.querySelector('#the-table');
function populateTable() {
const trStrings = [];
for (let i = 0; i < 4000; i++) {
const tdValues = [];
for (let j = 0; j < 10; j++) {
tdValues.push(i + '_' + j);
}
trStrings.push('<tr><td>' + tdValues.join('</td><td>') + '</td></tr>');
}
table.innerHTML = trStrings.join('');
log('table populated at ', (new Date().getTime() - t1), 'ms');
}
setTimeout(populateTable, 0);
const t1=new Date().getTime();
const log=console.log;
const table=document.querySelector(“#表”);
函数populateTable(){
常量trStrings=[];
for(设i=0;i<4000;i++){
常量tdValues=[];
for(设j=0;j<10;j++){
tdValues.push(i+'.'+j);
}
trStrings.push(“”+tdValues.join(“”)+“”);
}
table.innerHTML=trStrings.join(“”);
日志('表填充在',(new Date().getTime()-t1),'ms');
}
setTimeout(populateTable,0);
统计数据:
(索引):在79毫秒时填充80个表
(索引):在78毫秒时填充80个表格
(索引):在77毫秒时填充80个表格
(索引):在73毫秒时填充80个表
(索引):81毫秒时填充80个表
从某种意义上说,它仍然是“阻塞”,如果需要,它仍然可以被解决,但它的数量级更快,因此阻塞问题不那么令人担忧
但如果可能的话,这确实应该通过服务器提供,而不是通过Javascript进行动态解析和呈现。哇,我迟到了。作为类似的回答,我使用vanilla JS、promise和函数式编程更快地绘制表格 非阻塞的一个关键原因是表应该在内存中创建。将TR插入此内存表中。最后,循环完成后,将表插入DOM。代码如下:
const generateTable = () => {
return new Promise((resolve) => {
const table = document.createElement('table');
const column = Array.from({ length: 4000}, (v, i) => i);
const row = Array.from({ length: 10}, (v, i) => i);
column.forEach((col, i) => {
const tr = document.createElement('tr');
row.forEach((r, j) => {
const td = document.createElement('td');
td.innerHTML = `${i}-${j}`;
tr.appendChild(td);
})
table.appendChild(tr);
})
table.id = 'the-table';
resolve(table);
})
}
const t1 = new Date().getTime();
generateTable()
.then(table => {
document.body.appendChild(table);
console.log('table populated at ', (new Date().getTime() - t1), 'ms');
})
开始,创建需要插入到表中的所有内容。将
的内容添加到(4000行+40000个单元格)中后,创建一个
。这是唯一提交的DOM交互
添加一个
一次是在公园里散步
中是非常昂贵的
结束标记之前,因此不需要考虑阻塞
用户界面
var t0=新日期().getTime();
var frag=document.createDocumentFragment();
var tb=document.createElement('tbody');
for(设i=0;i<4000;i++){
const tr=document.createElement('tr');
for(设j=0;j<10;j++){
const td=document.createElement('td');
td.textContent=`i}{j}`;
tr.appendChild(td);
}
儿童结核病;
}
肺结核;
文件.getElementById('table01').appendChild(frag);
var t1=new Date().getTime();
document.getElementById('msg')。value=`插入所用的时间:${t1-t0}`;
将它们附加到tbody元素,然后将该tbody元素附加到表中。