Google Chrome 中的 DOM 过载问题

Ser*_*nov 7 html javascript dom

在 Google Chrome 中使用大量隐藏项目时遇到一些问题。

最近,我发布了一个很多人认为晦涩难懂的问题,很快就被关闭了。我找到了这个问题的原因,但到目前为止我不知道如何解决它。

有时在开发页面时,会使用一种方法,即预先创建一些元素并隐藏,然后在必要时显示。

所以此类元素的数量会极大地影响浏览器的响应速度。假设我们有以下代码:

var elem = document.getElementsByClassName ('Founder') [0];
var parent = document.getElementsByClassName ('Cloud') [0];
var empty = document.getElementsByClassName ('empty') [0];
for (var i = 0; i <50000; i ++) {
var clone = elem.cloneNode (true);
    // var clone = empty.cloneNode (true);
clone.style.display = 'none';
        parent.appendChild (clone);
    }
Run Code Online (Sandbox Code Playgroud)
<div class = 'Cloud'>
<input class = 'Founder' type = 'text'>
<div class = 'empty'> </div>
</div>
Run Code Online (Sandbox Code Playgroud)

因此,当我在 Firefox(67.0(64 位))中启动它时,没有特殊的刹车。但是当我在 Chrome 版本 74.0.3729.169(官方版本)(64 位)中运行它时,我得到了强大的刹车。

在配置文件中,这可以被视为空任务(系统)。看看截图。(它来自旧主题,总共有640,000个节点,但这不改变本质)。

性能工具显示缓慢的任务

有没有办法加快工作速度,我可以冻结没有显示的项目吗?据我了解这些空任务,这是浏览器索引元素或类似内容的时间。

也许可以通过编程方式更改任何设置,这将加快工作速度(可能需要更多 RAM)。

Kei*_*ith 2

parent.appendChild(...);是缓慢的一步。您要向文档添加 50,000 个节点,即使是隐藏的(这应该避免回流布局步骤),它们也将是一个需要添加的大量工作。

将它们添加到 a 中DocumentFragment会有帮助,但如果您想快速渲染 640,000 个节点,效果就没有那么大了。

提前创建元素然后显示它们可能是避免用户交互卡顿的有效方法,但大型文档通常速度较慢,并且大量节点很难快速生成。

我认为你有两个选择:

  1. 将更改批处理为较小的工作,并用于requestAnimationFrame等待下一帧执行下一批。当浏览器在所有新 DOM 上运行时,这种方式将阻止卡顿和明显的第二次左右,但总体上会花费更多时间。或者,当其他工作没有发生时,您可以requestIdleCallback在后台构建大量文档。对于其中任何一个,您都可能会遇到一个问题:文档显示为交互式,但隐藏的 DOM 节点尚不可用,因此您必须对此进行管理。

  2. 切换到根据需要添加 DOM,然后只优化该 DOM。创建一些其他对象来管理所有数据(您甚至可以使用 aWorkerComlink将所有数据保留在主 JS 线程之外)。这通常会更快,并且是大多数应用程序所做的,但是您将需要更多的工作来优化响应用户操作的性能(他们可能会等待 8 秒来等待您的应用程序最初加载,但如果他们单击他们期望的内容100 毫秒左右的时间)。