【发布时间】:2017-12-12 07:15:09
【问题描述】:
我对 JS 的性能有疑问。
说,我得到了下一个代码:
var divContainer = document.createElement("div"); divContainer.id="container";
var divHeader = document.createElement("div"); divHeader.id="header";
var divData = document.createElement("div"); divData.id="data";
var divFooter = document.createElement("div"); divFooter.id="footer";
divContainer.appendChild( divHeader );
divContainer.appendChild( divData );
divContainer.appendChild( divFooter );
document.getElementById("someElement").appendChild( divContainer );
这段代码只是为其他一些函数创建了一个shell来创建一个网格,创建网格的过程非常复杂并且有很多验证,目前我正在使用两种方法来填充网格,一种是在其中创建整个 html一个数组变量,另一个创建元素并将它们附加到documentFragment。
我的问题是,据我了解,使用片段时性能是否真的有所改善——它们在内存中管理元素,因此它们不会附加到文档,因此不会触发 DOM 重新计算和其他讨厌的东西。但是我创建变量的方式是,在我将容器附加到实际页面之前,它们不会附加到任何 DOM 元素。
所以我想知道以前的代码是否比使用像这样包装它的文档片段具有更好的性能:
var fragment = document.createDocumentFragment();
var divContainer = document.createElement("div"); divContainer.id="container";
var divHeader = document.createElement("div"); divHeader.id="header";
var divData = document.createElement("div"); divData.id="data";
var divFooter = document.createElement("div"); divFooter.id="footer";
divContainer.appendChild( divHeader );
divContainer.appendChild( divData );
divContainer.appendChild( divFooter );
fragment.appendChild( divContainer )
document.getElementById("someElement").appendChild( fragment.cloneNode(true) );
正如我已经说过的,这是一个关于性能的问题,我知道作为最佳实践建议使用片段,但我无法忘记这样做只会创建一个新对象在内存中并且什么都不做,所以我认为在这种情况下放弃片段是有效的。
希望有 js 大师/大神能在这里点亮希望之光,帮助我们解决这个问题。
编辑:所以,我一直在寻找与此问题相关的内容,似乎 documentFragments 并不一定意味着更好的性能。
它只是一个“内存中”的节点容器。片段和<div> 之间的区别在于片段没有父级,它永远不会在 DOM 上,只是在内存中,这意味着对片段进行的操作更快,因为没有对 DOM 的操作.
W3C关于documentFragments 的文档非常模糊,但重点是,大家最喜欢的浏览器并没有使用真正的片段,而是根据this MSDN documentation 创建一个新文档。这意味着 IE 上的 Fragment 速度较慢。
所以,问题是,如果我创建一个元素(例如 <div>)在变量中但不要将其附加到 DOM,添加元素(div、表格等)等所有工作完成后(循环、验证、元素样式),附加该元素,是否与片段?
鉴于 IE 使用“假”片段这一事实我会说至少在 IE 中使用这种方法(使用诸如 div 之类的元素,而不是片段)更好,我真的不在乎 IE 但我需要测试它(办公室的政策)。
另外,如果我像这样在数组上创建所有 html:
var arrHTML = ["<table>","<tr>", ....];
然后这样做
document.getElementById("someElement").innerHTML = arrHTML.join("");
在 IE 上速度更快,但其他主要浏览器(FF、Chrome、Safari 和 Opera)在使用容器然后附加它(片段或 div)时表现更好。
所有这一切都是因为创建所有元素的过程非常快,大约需要 8 - 10 秒来创建多达 24 列的 20,000 行,这是很多元素/标签,但浏览器似乎冻结了几秒钟后它们都被一次附加,如果我尝试一个接一个地附加它们,那就太糟糕了。
再次感谢大家,这真的很有趣。
【问题讨论】:
-
粘贴在 jsperf 上,看看在目标受众的浏览器上哪个更快。
-
我在 firefox 和 chrome 中使用了控制台的配置文件,它们都在同一时间(大约 180 毫秒)执行,标题和数据 div 中有真实数据,我已经测试了“香草”方式,没有片段,只是将所有内容附加到一个硬币容器,然后该容器将其附加到 DOM,还使用片段并在变量上创建整个 html,然后向该变量添加一个 innerHTML,它们似乎都或多或少地工作相同,但我的问题是性能方面的,这对于内存和类似的东西来说更好。谢谢
-
据我了解,您会使用文档片段来避免大量回流,但如果您只是附加少量(例如您所显示的),那真的不值得它。
-
要追加的元素越多,性能差异就越大。
-
@jbabey jsPerf 测试结果可能会产生误导。很难构建一个真正代表真实世界 DocumentFragment 使用的 jsPerf 测试。使用 DocumentFragments 的主要好处是可以避免昂贵的页面重排和/或 DOM 遍历。此处的 jsPerf 测试都没有展示避免页面重排带来的性能提升,只有 wolfram77 给出的答案展示了通过使用 DocumentFragments 避免大量 DOM 遍历所节省的成本。
标签: javascript performance documentfragment