一、前言

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

二、DocumentFragment对象是什么?

MDN解释:

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

W3C解释:

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

怎么去理解呢?我们结合上面两解释可以得知,DocumentFragment 节点不属于DOM树,因此它的变化不会引起DOM树的变化;

我们知道,DOM树的操作会引起回流,那我们可以将DocumentFragment作为一个暂时的DOM节点存储器,当我们在DocumentFragment 修改完成时,我们就可以将存储DOM节点的DocumentFragment一次性加入DOM树,从而减少回流次数,达到性能优化的目的。

三、DocumentFragment对象怎么用?

我们可以使用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); //

使用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对象

页面优化,DocumentFragment对象详解的更多相关文章

  1. Window 对象详解 转自 http://blog.csdn.net/jcx5083761/article/details/41243697

    详解HTML中的window对象和document对象 标签: HTMLwindowdocument 2014-11-18 11:03 5884人阅读 评论(0) 收藏 举报 分类: HTML& ...

  2. mvc-servlet---ServletConfig与ServletContext对象详解(转载)

    ServletConfig与ServletContext对象详解 一.ServletConfig对象    在Servlet的配置文件中,可以使用一个或多个<init-param>标签为s ...

  3. JavaWeb学习----JSP内置对象详解

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  4. django中request对象详解(转载)

    django中的request对象详解 Request 我们知道当URLconf文件匹配到用户输入的路径后,会调用对应的view函数,并将  HttpRequest对象  作为第一个参数传入该函数. ...

  5. dom对象详解--document对象(一)

     document对象 Document对象代表整个html文档,可用来访问页面中的所有元素,是最复杂的一个dom对象,可以说是学习好dom编程的关键所在. Document对象是window对象的一 ...

  6. js对象详解(JavaScript对象深度剖析,深度理解js对象)

    js对象详解(JavaScript对象深度剖析,深度理解js对象) 这算是酝酿很久的一篇文章了. JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕 ...

  7. Angular.js中处理页面闪烁的方法详解

    Angular.js中处理页面闪烁的方法详解 前言 大家在使用{{}}绑定数据的时候,页面加载会出现满屏尽是{{xxx}}的情况.数据还没响应,但页面已经渲染了.这是因为浏览器和angularjs渲染 ...

  8. Vue实例初始化的选项配置对象详解

    Vue实例初始化的选项配置对象详解 1. Vue实例的的data对象 介绍 Vue的实例的数据对象data 我们已经用了很多了,数据绑定离不开data里面的数据.也是Vue的核心属性. 它是Vue绑定 ...

  9. jQuery的deferred对象详解

    jQuery的deferred对象详解请猛击下面的链接 http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_ ...

随机推荐

  1. Oracle在.sql文件中创建存储过程

    创建存储过程的语法网上到处都有. 可我执行了半天都创建不成功. 最后,发现! 在最后加个 / 就可以了!!! 真坑啊 今天连续被Oracle坑了两次了. 最后,感谢这个人https://blog.cs ...

  2. vscode1.30.1使用的electron3.0.10中的bug

    PS C:\GitHub\vscode2\vscode> scripts\code.bat[13:07:19] Syncronizing built-in extensions...[13:07 ...

  3. Matlab调用遗传工具箱复现论文模型求解部分

    原文转载自:https://blog.csdn.net/robert_chen1988/article/details/52431594 论文来源: https://www.sciencedirect ...

  4. node08

    ---恢复内容开始--- 1.Axios 1)基于promise的HTTP库,可用在浏览器或nodejs中 2)使用方法: 在模块内使用需要挂载到Vue对象上: Vue.prototype.$axio ...

  5. php调用第三方接口

    方式一 $url = 'http://ip.taobao.com/service/getIpInfo.php?ip='.$realip;$data = file_get_contents(" ...

  6. 矢量图形(vector graphics)和位图图像(bitmap)以及分辨率概念

    第一篇:凭心而论.客观地认识矢量图形与位图图像http://www.dzwebs.net/2003.html 学习过物理的人都明白,矢量有大小和方向,而标量只有大小却没有方向: 但是在计算机里面,图形 ...

  7. Python连接MySQL数据库之pymysql模块使用

    安装PyMySQL pip install pymysql PyMySQL介绍 PyMySQL是在python3.x版本中用于连接MySQL服务器的一个库,2中则使用mysqldb. Django中也 ...

  8. Openstack中RabbitMQ RPC代码分析

    在Openstack中,RPC调用是通过RabbitMQ进行的. 任何一个RPC调用,都有Client/Server两部分,分别在rpcapi.py和manager.py中实现. 这里以nova-sc ...

  9. iOS依赖库管理工具之Carthage

    在iOS开发中,我们常会用CocoaPods来进行依赖库的管理.CoaoaPods 是一套整体解决方案,我们在 Podfile 中指定好我们需要的第三方库,然后 CocoaPods 就会进行下载,集成 ...

  10. 【Nim游戏】高僧斗法

    先来看看Nim定理: // 若干堆硬币,二人轮流取,从一堆硬币中取几个 直到某个人不能取硬币 那这个人就输了 // 3 4 5 // 3 3 把硬币变成相同的 那么你就赢了 因为你可以跟着另一个人一样 ...