Javascript 如何延迟DOM元素的呈现以防止无响应

Javascript 如何延迟DOM元素的呈现以防止无响应,javascript,dom,browser,Javascript,Dom,Browser,我正在通过API调用从服务器获取大量人员(1000人)。 根据数据,我必须为每个用户呈现“卡片”,其中包含他们的姓名、图片、年龄等。 但当我这样做时,浏览器会被卡住一段时间,直到所有的卡片都呈现出来。有没有办法告诉浏览器,不必一次渲染所有内容,它可以一个接一个地渲染,而不会自己崩溃?看一看 如果向DOM中添加元素,页面将被重新绘制。如果一个接一个地添加100个元素,它将被重新绘制100次,这很慢。在将其附加到页面之前,创建单个容器并为其中的项目添加节点 var container = $('&l

我正在通过API调用从服务器获取大量人员(1000人)。
根据数据,我必须为每个用户呈现“卡片”,其中包含他们的姓名、图片、年龄等。

但当我这样做时,浏览器会被卡住一段时间,直到所有的卡片都呈现出来。有没有办法告诉浏览器,不必一次渲染所有内容,它可以一个接一个地渲染,而不会自己崩溃?

看一看

如果向DOM中添加元素,页面将被重新绘制。如果一个接一个地添加100个元素,它将被重新绘制100次,这很慢。在将其附加到页面之前,创建单个容器并为其中的项目添加节点

var container = $('<div>');

$.each(items, function (index, itm) {
    var el = $('<div>');
    el.attr('id', ID_PREFIX + index);
    el.html(createHtml(itm));
    container.append(el);
});

$('#list-container').append(container);
var容器=$('');
$。每个(项目、功能(索引、itm){
变量el=$('');
el.attr('id',id\u前缀+索引);
html(createHtml(itm));
容器。附加(el);
});
$(“#列出容器”).append(容器);
类似于上面的内容(使用jQuery,但使用普通JS也可以)

(当然,
createHtml
是一个实用函数,您可以定义它来获取项目的标记,
items
是包含数据的数组)

也就是说,我同意上面的@Bergi:您真的需要同时显示所有项目吗?你能设置一个滚动视图,当你向下滚动时它会被填充吗

接下来,您可以使用或高效地管理数据绑定。

看一看

如果向DOM中添加元素,页面将被重新绘制。如果一个接一个地添加100个元素,它将被重新绘制100次,这很慢。在将其附加到页面之前,创建单个容器并为其中的项目添加节点

var container = $('<div>');

$.each(items, function (index, itm) {
    var el = $('<div>');
    el.attr('id', ID_PREFIX + index);
    el.html(createHtml(itm));
    container.append(el);
});

$('#list-container').append(container);
var容器=$('');
$。每个(项目、功能(索引、itm){
变量el=$('');
el.attr('id',id\u前缀+索引);
html(createHtml(itm));
容器。附加(el);
});
$(“#列出容器”).append(容器);
类似于上面的内容(使用jQuery,但使用普通JS也可以)

(当然,
createHtml
是一个实用函数,您可以定义它来获取项目的标记,
items
是包含数据的数组)

也就是说,我同意上面的@Bergi:您真的需要同时显示所有项目吗?你能设置一个滚动视图,当你向下滚动时它会被填充吗


接下来,您可以使用或高效地管理数据绑定。

这里有几个选项。正如其他人所提到的,最好的选择是根本不渲染:

  • 使用“无限滚动”技术仅渲染所需内容。基本思想是通过检查滚动位置来删除屏幕外的DOM元素并添加屏幕上的DOM元素

  • 使用不同的用户驱动分页机制

除此之外,通过构造和设置
innerHTML
或使用文档片段,您可以一次性呈现所有内容,从而获得更好的性能。但是有了1000个元素,您仍然会得到较差的性能

此时,您可能需要批处理。这不会更快,但会释放UI,以便在渲染时不会锁定对象。非常基本的批处理方法可能如下所示:

// things to render
var items = [...];
var index = 0;
var batchSize = 100;
// time between batches, in ms
var batchInterval = 100;

function renderBatch(batch) {
    // rendering logic here
}

function nextBatch() {
    var batch = items.slice(index, index + batchSize);
    renderBatch(batch);
    index += batchSize;
    if (index < items.length - 1) {
        // Render the next batch after a given interval
        setTimeout(nextBatch, batchInterval);
    }
}

// kick off
nextBatch();
//要渲染的对象
var项目=[…];
var指数=0;
var-batchSize=100;
//批次之间的时间,单位为毫秒
var batchInterval=100;
函数renderBatch(批处理){
//这里呈现逻辑
}
函数nextBatch(){
var batch=items.slice(索引,索引+batchSize);
renderBatch(批量);
索引+=批量大小;
如果(索引

不过,值得注意的是,这是有限制的——渲染是一个瓶颈,但每个DOM元素也会影响客户端内存。对于1000个元素中的10个,即使在渲染完成后,事情也会变得缓慢和无响应,因为内存使用率非常高。

这里有一些选项。正如其他人所提到的,最好的选择是根本不渲染:

  • 使用“无限滚动”技术仅渲染所需内容。基本思想是通过检查滚动位置来删除屏幕外的DOM元素并添加屏幕上的DOM元素

  • 使用不同的用户驱动分页机制

除此之外,通过构造和设置
innerHTML
或使用文档片段,您可以一次性呈现所有内容,从而获得更好的性能。但是有了1000个元素,您仍然会得到较差的性能

此时,您可能需要批处理。这不会更快,但会释放UI,以便在渲染时不会锁定对象。非常基本的批处理方法可能如下所示:

// things to render
var items = [...];
var index = 0;
var batchSize = 100;
// time between batches, in ms
var batchInterval = 100;

function renderBatch(batch) {
    // rendering logic here
}

function nextBatch() {
    var batch = items.slice(index, index + batchSize);
    renderBatch(batch);
    index += batchSize;
    if (index < items.length - 1) {
        // Render the next batch after a given interval
        setTimeout(nextBatch, batchInterval);
    }
}

// kick off
nextBatch();
//要渲染的对象
var项目=[…];
var指数=0;
var-batchSize=100;
//批次之间的时间,单位为毫秒
var batchInterval=100;
函数renderBatch(批处理){
//这里呈现逻辑
}
函数nextBatch(){
var batch=items.slice(索引,索引+batchSize);
renderBatch(批量);
索引+=批量大小;
如果(索引

不过,值得注意的是,这是有限制的——渲染是一个瓶颈,但每个DOM元素也会影响客户端内存。对于1000个元素中的10个,即使在渲染完成后,事情也会变得缓慢和无响应,因为内存使用率太高。

使用
setTimeout
一次向DOM添加较少的元素可能只是不将1000张卡渲染到屏幕上?无论如何,它们不会一次全部显示出来。@Bergi:1000只是一个随机数,问题是关于preven的