页面优化,DocumentFragment对象详解

1、前言html

最近项目不是很忙,因此去看了下以前总想整理的重汇和回流的相关资料,关于回流优化,提到了DocumentFragment的使用,这个对象在3年前我记得是有看过的,可是一直没深刻了解过,因此这里作个整理。后面会把重汇,回流也作个整理,不鸽。node

2、DocumentFragment对象是什么?性能优化

MDN解释:app

DocumentFragment 表示一个没有父级文件的最小文档对象。它被当作一个轻量版的 Document 使用,用于存储已排好版的或还没有打理好格式的XML片断。最大的区别是由于DocumentFragment不是真实DOM树的一部分,它的变化不会引发DOM树的从新渲染的操做(reflow) ,且不会致使性能等问题。---MDNdom

W3C解释:性能

 DocumentFragment 接口表示文档的一部分(或一段)。更确切地说,它表示一个或多个邻接的 Document 节点和它们的全部子孙节点。 DocumentFragment 节点不属于文档树,继承的 parentNode 属性老是 null。 不过它有一种特殊的行为,该行为使得它很是有用,即当请求把一个 DocumentFragment 节点插入文档树时,插入的不是 DocumentFragment 自身,而是它的全部子孙节点。这使得 DocumentFragment 成了有用的占位符,暂时存放那些一次插入文档的节点。它还有利于实现文档的剪切、复制和粘贴操做,尤为是与 Range 接口一块儿使用时更是如此。 能够用 Document.createDocumentFragment() 方法建立新的空 DocumentFragment 节点。---W3C优化

怎么去理解呢?咱们结合上面两解释能够得知,DocumentFragment 节点不属于DOM树,所以它的变化不会引发DOM树的变化;spa

咱们知道,DOM树的操做会引发回流,那咱们能够将DocumentFragment做为一个暂时的DOM节点存储器,当咱们在DocumentFragment 修改完成时,咱们就能够将存储DOM节点的DocumentFragment一次性加入DOM树,从而减小回流次数,达到性能优化的目的。code

3、DocumentFragment对象怎么用?xml

咱们可使用document.createDocumentFragment()建立一个DocumentFragment,每一个新建的DocumentFragment都会继承全部node方法。且DocumentFragment拥有nodeValue,nodeName,nodeType属性。

let fragment =  document.createDocumentFragment();
console.log(fragment.nodeValue); //null
console.log(fragment.nodeName); //#document-fragment
console.log(fragment.nodeType); //11

使用DocumentFragment能解决直接操做DOM引起大量回流的问题,好比咱们要给ul添加五个li节点,区别就像这样:

直接操做DOM,回流五次:

使用DocumentFragment一次性添加,回流一次:

假设咱们给ul加入五万个li,分别对比下渲染完成时间:

html:
<body>
    <ul id="list"></ul>
    <ul id="list1"></ul>
</body>


js:
//使用documentFragment添加节点
console.time("time")
let list = document.querySelector("#list"),
    fragment = document.createDocumentFragment(),
    n = 50000;
while(n--){
  fragment.appendChild(document.createElement("li"));
};
list.appendChild(fragment);
console.timeEnd("time")

//直接操做DOM添加节点
console.time("time1")
let list1 = document.querySelector("#list1"),
    i = 50000;
while(i--){
  list1.appendChild(document.createElement("li"))
};
console.timeEnd("time1")

多刷新几回对比二者的耗时,time是使用了DocumentFragment的耗时,time1是直接添加DOM的耗时

很明显,time比time1耗时要短不少。

再刷新几回试试

很明显,屡次刷新反而还会出现使用DocumentFragment耗时更久的状况,性能更差?打脸了。暂时没法解释,但愿有大佬能说说。

不过读到这,也明白了DocumentFragment是个什么东西,怎么使用它,那么本文就到这里结束了。

 

参考资料

深刻理解DOM节点类型第四篇——文档片断节点DocumentFragment

DocumentFragment对象

相关文章
相关标签/搜索