Javascript 如何加快向DOM添加大量复杂HTML的速度

Javascript 如何加快向DOM添加大量复杂HTML的速度,javascript,html,ajax,dom,Javascript,Html,Ajax,Dom,我有一个普通的网页,它通过AJAX调用加载大部分内容,AJAX调用返回大量复杂的HTML。当我将检索到的HTML放在DOM中时,它会使浏览器瘫痪相当长一段时间,在Chrome上为5秒,在Edge上为35秒 我如何将HTML附加到DOM的示例: $.ajax("example.php").done(function (response) { const contentElement = document.getElementById('results'); contentEleme

我有一个普通的网页,它通过AJAX调用加载大部分内容,AJAX调用返回大量复杂的HTML。当我将检索到的HTML放在DOM中时,它会使浏览器瘫痪相当长一段时间,在Chrome上为5秒,在Edge上为35秒

我如何将HTML附加到DOM的示例:

$.ajax("example.php").done(function (response) {
    const contentElement = document.getElementById('results');
    contentElement.innerHTML = response;
});
我希望避免因为应用程序的复杂性而不惜一切代价返回JSON并将其转换为HTML

奇怪的是,在插入的HTML已经可见后不久,浏览器就会瘫痪。请参阅下面的时间线,在5秒长的解析HTML事件发生之前,我可以在屏幕上看到具有适当样式的HTML

如何加快HTML到DOM的解析和附加速度

编辑:我尝试了多种浏览器和多种注入HTML文档片段、innerHTML、jquery.HTML、append的方法。所有的方法大致都一样慢


Edit2:注入的确切HTML可以在下面的要点中看到:

简单地将您提供的HTML附加或插入到浏览器中似乎没有任何负面影响。至少在我的浏览器/计算机上。铬

运行此示例,查看是否遇到任何延迟或暂停

显然,这不是一个完整的测试,因为我丢失了您的CSS,我通过删除换行符稍微修改了您的html,以便我可以将文本分配给文本编辑器中的变量

如果这个示例对您有效,那么我们需要进一步调查来自服务器的数据,并尝试将css添加到等式中,等等


如果该示例导致延迟,则问题可能与硬件有关,可能是因为您没有足够的可用内存和/或cpu,导致浏览器瘫痪。

只需将您提供的HTML附加或插入浏览器中,似乎不会产生任何不利影响。至少在我的浏览器/计算机上。铬

运行此示例,查看是否遇到任何延迟或暂停

显然,这不是一个完整的测试,因为我丢失了您的CSS,我通过删除换行符稍微修改了您的html,以便我可以将文本分配给文本编辑器中的变量

如果这个示例对您有效,那么我们需要进一步调查来自服务器的数据,并尝试将css添加到等式中,等等

如果该示例导致延迟,则问题可能与硬件有关,可能是因为您没有足够的可用内存和/或cpu,导致浏览器瘫痪。

第1部分-这不是加载代码的方式,只是代码无效,即使在页面上硬编码也无法工作。 奇怪的是,在插入的HTML已经可见后不久,浏览器就会瘫痪。请参阅下面的时间线,在5秒长的解析HTML事件发生之前,我可以在屏幕上看到具有适当样式的HTML

关于HTML的实用性,有一些问题需要解决——它的荒谬之处不言而喻,它的有效性不存在,功能性不存在,也可能从未存在过

你应该这样做,因为它是非常无效的,但在我们开始之前,当你决定验证这个混乱时,你需要将它分成大约16个部分,因为大多数在线服务都会失败,或者如果一次处理那么多,那么验证过程就会提前结束

以下是由于打字错误而非孤立问题的列表。这些问题重复了多次。我最担心的是,这些值和大多数变量似乎都是手工定制的。希望我弄错了,你没有花几个小时来定制那些会阻碍而不是真正有用的值。

1. - 在任何情况下,同一页上都不应存在重复的ID。 14个手风琴固定,14个单头固定,7个型号,7个型号,7个品牌

有更多的被骗ID,我把手风琴改成了第1到14条,因为每个手风琴都需要发挥作用,而不仅仅是第一个。所有与accordion有直接关系的相关属性也需要更改,为了再次实现功能,我设法更改了toggle parent=accordion。所以有15个手风琴,我添加了一个主页标签,上面有一个设计合理的手风琴,如果你决定重新设计其他14个手风琴,你可以用它作为模板。

2.要使用引导组件,请根据文档制作它们。 OP代码甚至没有任何标签,如果你提到了,甚至,你会知道你需要有一个是OP原始帖子问题的解决方案,这在本答案的第2部分中有详细解释。HTML已经部分修复,我没有足够的时间修复所有内容

它有16个标签和15个手风琴

Loa d时间已从34秒缩短为2秒。有棱角。Edge似乎英勇地尝试理解解析后失败的HTML。真正的浏览器,如Firefox和Chrome,只是将其转储并保留在那里

是OP代码中的HTML,我的解决方案正在加载它

结果是一样的,OP代码失败是因为代码本身,而不是因为加载问题

第2部分-将巨大字符串解析为HTML的稳定方法。如果操作代码实际工作,则不需要。 当试图通过innerHTML向DOM添加大量标记时,OP遇到严重延迟。最多34秒,使用Edge完全渲染,而其他浏览器在3秒时报告

我在Edge上的加载时间缩短到了2到3秒,在真正的浏览器Chrome和Firefox上也能立即加载

虽然OP已经尝试过使用,但我相信它是快速加载和解析HTML的关键。OP可能没有使用的其他关键组件包括: 及

使用insertAdjacentHTML方法而不是innerHTML属性。insertAdjacentHTML是innerHTML的一个功能强大且通用的版本

相似之处:

两者都将接受给定的字符串并解析为HTML

两者都很快

差异:

insertAdjacentHTML将HTML插入DOM,它不会覆盖元素中或DOM中任何地方的任何现有HTML。innerHTML覆盖元素的内部

innerHTML通过引用一个元素来定向,它将获取一个字符串并用给定的字符串覆盖该元素的所有内容。如果innerHTML只是指向一个没有字符串的元素,那么它将返回该元素的HTML内容。innerHTML获取的能力是insertAdjacentHTML唯一做不到的。相反,insertAdjacentHTML的设置功能非常强大,正如所解释的:insertAdjacentHTML不仅通过引用元素来定向,而且通过其第一个参数(与位置相关的4个DOMString中的一个)来准确地告知相对于被引用元素的方向:

beforebeagin将字符串放在元素开头的正前方

      `$elector.before(str)`★
      `$elector.after(str)`★
afterend将字符串放在元素末尾的正后方

      `$elector.before(str)`★
      `$elector.after(str)`★
afterbegin将字符串放置在brginning之后的元素中。换句话说,字符串插入到元素内容之前

     `$elector.prepend(str)`★
beforeend将字符串放在元素的末尾之前。基本上,字符串放在元素内容之后。该位置是速度方面最优化的位置,因为该位置不会使速度减慢

     `$elector.append(str)`★
insertAdjacentHTML第二个参数是将被解析为HTML的字符串。使用而不是文字字符串可以让我们更轻松地处理字符串

    `element.insertAdjacentHTML("beforeend", <input id="${ID+i}" type="${typeArr[i]}" value="${Math.floor(Math.random() * i}">)`
DOM操作是处理器密集型的,我们越是避免它越好。DocumentFragment是为了让我们完成所有涉及DOM的琐碎而繁杂的任务而制作的。我们可以向DocumentFragment及其子体添加任意多的元素、文本、属性、设置事件处理程序等,而无需接触DOM。完成所有操作后,只需执行一个DOM操作:

 `document.body.appendChild(frag);` 
演示-如果您想测试实际工作的演示,请查看此 巨大而丑陋之物 作用{ const str=` HTML的巨大灾难` const frag=document.createDocumentFragment; const node=document.createElement'div'; 让build=functionnode,str,frag{ node.insertAdjacentHTML'beforeend',str; frag.appendChildnode; document.body.appendChildfrag; } buildnode,str,frag; }; 第1部分-这不是加载代码的方式,只是代码无效,即使在页面上硬编码也无法工作。 奇怪的是,在插入的HTML已经可见后不久,浏览器就会瘫痪。请参阅下面的时间线,在5秒长的解析HTML事件发生之前,我可以在屏幕上看到具有适当样式的HTML

关于HTML的实用性,有一些问题需要解决——它的荒谬之处不言而喻,它的有效性不存在,功能性不存在,也可能从未存在过

你应该这样做,因为它是非常无效的,但在我们开始之前,当你决定验证这个混乱时,你需要将它分成大约16个部分,因为大多数在线服务都会失败,或者如果一次处理那么多,那么验证过程就会提前结束

以下是由于打字错误而非孤立问题的列表。这些问题重复了多次。我最担心的是,这些值和大多数变量似乎都是手工定制的。希望我弄错了,你没有花几个小时来定制那些会阻碍而不是真正有用的值。

1. - 在任何情况下都不应该有复制品 在同一页上添加了ID。 14个手风琴固定,14个单头固定,7个型号,7个型号,7个品牌

有更多的被骗ID,我把手风琴改成了第1到14条,因为每个手风琴都需要发挥作用,而不仅仅是第一个。所有与accordion有直接关系的相关属性也需要更改,为了再次实现功能,我设法更改了toggle parent=accordion。所以有15个手风琴,我添加了一个主页标签,上面有一个设计合理的手风琴,如果你决定重新设计其他14个手风琴,你可以用它作为模板。

2.要使用引导组件,请根据文档制作它们。 OP代码甚至没有任何标签,如果你提到了,甚至,你会知道你需要有一个是OP原始帖子问题的解决方案,这在本答案的第2部分中有详细解释。HTML已经部分修复,我没有足够的时间修复所有内容

它有16个标签和15个手风琴

加载时间已从34秒缩短为2秒。有棱角。Edge似乎英勇地尝试理解解析后失败的HTML。真正的浏览器,如Firefox和Chrome,只是将其转储并保留在那里

是OP代码中的HTML,我的解决方案正在加载它

结果是一样的,OP代码失败是因为代码本身,而不是因为加载问题

第2部分-将巨大字符串解析为HTML的稳定方法。如果操作代码实际工作,则不需要。 当试图通过innerHTML向DOM添加大量标记时,OP遇到严重延迟。最多34秒,使用Edge完全渲染,而其他浏览器在3秒时报告

我在Edge上的加载时间缩短到了2到3秒,在真正的浏览器Chrome和Firefox上也能立即加载

虽然OP已经尝试过使用,但我相信它是快速加载和解析HTML的关键。OP可能没有使用的其他关键组件包括: 及

使用insertAdjacentHTML方法而不是innerHTML属性。insertAdjacentHTML是innerHTML的一个功能强大且通用的版本

相似之处:

两者都将接受给定的字符串并解析为HTML

两者都很快

差异:

insertAdjacentHTML将HTML插入DOM,它不会覆盖元素中或DOM中任何地方的任何现有HTML。innerHTML覆盖元素的内部

innerHTML通过引用一个元素来定向,它将获取一个字符串并用给定的字符串覆盖该元素的所有内容。如果innerHTML只是指向一个没有字符串的元素,那么它将返回该元素的HTML内容。innerHTML获取的能力是insertAdjacentHTML唯一做不到的。相反,insertAdjacentHTML的设置功能非常强大,正如所解释的:insertAdjacentHTML不仅通过引用元素来定向,而且通过其第一个参数(与位置相关的4个DOMString中的一个)来准确地告知相对于被引用元素的方向:

beforebeagin将字符串放在元素开头的正前方

      `$elector.before(str)`★
      `$elector.after(str)`★
afterend将字符串放在元素末尾的正后方

      `$elector.before(str)`★
      `$elector.after(str)`★
afterbegin将字符串放置在brginning之后的元素中。换句话说,字符串插入到元素内容之前

     `$elector.prepend(str)`★
beforeend将字符串放在元素的末尾之前。基本上,字符串放在元素内容之后。该位置是速度方面最优化的位置,因为该位置不会使速度减慢

     `$elector.append(str)`★
insertAdjacentHTML第二个参数是将被解析为HTML的字符串。使用而不是文字字符串可以让我们更轻松地处理字符串

    `element.insertAdjacentHTML("beforeend", <input id="${ID+i}" type="${typeArr[i]}" value="${Math.floor(Math.random() * i}">)`
DOM操作是处理器密集型的,我们越是避免它越好。DocumentFragment是为了让我们完成所有涉及DOM的琐碎而繁杂的任务而制作的。我们可以向DocumentFragment及其子体添加任意多的元素、文本、属性、设置事件处理程序等,而无需接触DOM。完成所有操作后,只需执行一个DOM操作:

 `document.body.appendChild(frag);` 
演示-如果您想测试实际工作的演示,请查看此 巨大而丑陋之物 作用{ const str=` HTML的巨大灾难` const frag=document.createDocumentFragment; const node=document.createElement'div'; 让build=functionnode,str,frag{ node.insertAdjacentHTML'beforeend',str; frag.appendChildnode; document.body.appendChildfrag; } buildnode,str,frag; };
我通过特雷弗和泽尔的回答解决了这个问题,但情况完全不同

问题是由默认情况下跟踪AJAX请求并解析响应f的
或调试目的。在Debugbar配置中禁用AJAX请求跟踪解决了这个问题

我通过特雷弗和泽尔的回答解决了这个问题,但情况完全不同


该问题是由默认情况下跟踪AJAX请求并解析响应以进行调试而引起的。在Debugbar配置中禁用AJAX请求跟踪解决了这个问题

你能展示一个你试图解析的html的例子吗?@floor我已经添加了html的要点,提前感谢这可能会有帮助,谢谢@Jimenemex,但是当你放置多个项目(比如从一个循环中)并收集它时,documentFragment很有用,这样你就可以一次性将它放置在DOM中。但是,在我的例子中,我已经把所有的HTML放在一起了。你能展示一个你试图解析的HTML的例子吗?@floor我已经添加了HTML的要点,提前感谢这可能会有帮助,谢谢@Jimenemex,但是documentFragment在你放置多个项目时很有用,比如从一个循环,并将其收集起来,以便一次性将其放入DOM中。然而,在我的例子中,我已经把所有的HTML放在一起,并把它放在一块。谢谢你详细的回答。您对重复ID的看法是正确的,但是,尽管这是一种不好的做法,但它不会破坏HTML的解析和呈现。我修复了重复的ID,这并没有造成真正的性能差异。稍后我仍将尝试您的其他建议,以进一步提高性能,但我解决了真正的性能问题,请参阅我自己的答案。感谢您详细的回答。您对重复ID的看法是正确的,但是,尽管这是一种不好的做法,但它不会破坏HTML的解析和呈现。我修复了重复的ID,这并没有造成真正的性能差异。稍后我仍将尝试您的其他建议,以进一步提高性能,但我解决了真正的性能问题,请参见我自己的答案。