首页 > 解决方案 > Google Chrome 中的 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);
    }
<div class = 'Cloud'>
<input class = 'Founder' type = 'text'>
<div class = 'empty'> </div>
</div>

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

在配置文件中,这可以看作是空任务(系统)。看截图。(来自老主题,一共有64万个节点,但这并没有改变本质)。

显示缓慢任务的性能工具

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

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

标签: javascripthtmldom

解决方案


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

将它们添加到 aDocumentFragment会有所帮助,但如果您想快速渲染 640,000 个节点,则效果不大。

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

我认为你有两个选择:

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

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


推荐阅读