深入理解DocumentFragment -文档片段

news/2024/9/19 14:05:53/文章来源:https://www.cnblogs.com/yang10086/p/18407890

什么是文档片段?

(MDN解释:)DocumentFragment,文档片段接口,一个没有父对象的最小文档对象。它被作为一个轻量版的 Document 使用,就像标准的document一样,存储由节点(nodes)组成的文档结构。

作用是什么

与document相比,最大的区别是DocumentFragment 不是真实 DOM 树的一部分,它的变化不会触发 DOM 树的重新渲染,且不会导致性能等问题。

怎么使用DocumentFragment

let fragement = document.createDocumentFragment()console.log(fragement.nodeName)//#document-fragmentconsole.log(fragement.nodeType)//11console.log(fragement.nodeValue)//nullconsole.log(fragement.parentNode)//null

通常情况下,我们使用Node.appendChild 和 Node.insertBefore 的方法,往dom元素添加元素。每个节点分别被插入到文档中,这样会发生多次重新渲染,造成页面回流的操作,则会非常消耗性能,影响用户体验。

DocumentFragment解决了什么?

使用DocumentFragment能解决直接操作DOM引发大量回流的问题,因为所有的节点会被一次插入到文档中,而这个操作仅发生一个重渲染的操作,比如我们要给ul添加五个li节点,区别就像这样:
直接操作DOM,回流五次:

let app = document.querySelector('.app')for(let i = 0;i<5;i++){let div = document.createElement('li')div.setAttribute('class','item')div.innerText = 6666app.appendChild(div)}

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

let app = document.querySelector('.app')let fragement = document.createDocumentFragment()for(let i = 0;i<5;i++){let div = document.createElement('li')div.setAttribute('class','item')div.innerText = 6666fragement.appendChild(div)}app.appendChild(fragement)

总结:DocumentFragment节点不属于文档树,存在于内存中,并不在DOM中,所以将子元素插入到文档片段中时不会引起页面回流,因此使用DocumentFragment可以起到性能优化的作用。

渲染引擎中JS对文档操作不是同步。你上述的实例代码,在执行效率上几乎一样,甚至直接操作DOM效率会更高。
一般情况下,JS中对DOM的操作会在JS执行完成之后再进行layout的更新,也就是说只会一次回流,并不是文中所说的appendChild一次就重新渲染一次。
当然,如果你在for循环中进行了DOM的相应属性的查询操作,比如div.offsetWidth,那么直接操作DOM才会导致多次重新渲染。但是这牵涉到另一个概念,强制同步布局。

浏览器会缓存一些DOM和样式变动,所以少量的时候区别不大,但是大批量的时候DocumentFragment就有很大优势了,可以确保只有一次重排或重绘,但也有一些例外,offsetWidth、clientWidth、scrollWidth等属性的读操作或getComputedStyle、getBoundingClientRect、scrollTo等方法的调用是会导致浏览器立即重绘的

这些会导致立即重排,来获取最新的位置信息。
但是不会重绘,重绘是调用渲染线程。一个 task 没有完成,不会调用渲染线程。

原文

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/795369.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode Hot100刷题记录-141.环形链表

给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅…

[Python] Python 基础教程

1 概述 1.1 简介Python 是一种解释型、面向对象、动态数据类型的高级程序设计语言。https://www.python.org/Python 由 Guido van Rossum 于 1989 年底发明,第一个公开发行版发行于 1991 年。 像 Perl 语言一样, Python 源代码同样遵循 GPL(GNU General Public License) 协议。…

从数据洞察到智能决策:合合信息infiniflow RAG技术的实战案例分享

从数据洞察到智能决策:合合信息&infiniflow RAG技术的实战案例分享从数据洞察到智能决策:合合信息&infiniflow RAG技术的实战案例分享 标题取自 LLamaIndex,这个内容最早提出于今年 2 月份 LlamaIndex 官方博客。从 22 年 chatGpt 爆火,23 年大模型尝鲜,到 24 年真…

数据飞轮转进快递行业 能够为企业带来哪些新想象

快递行业的2024年下半场竞赛已然开始,鉴于双11、年货节等电商营销重要节点都集中在下半年,流转出快递行业在下半年的巨大市场机会,数据飞轮或许能成为更多快递企业的增长动力,转出更为稳健的业绩增长。更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【…

手动用梯度下降法和随机梯度下降法实现一元线性回归

手动用梯度下降法和随机梯度下降法实现一元线性回归(超详细)手动用梯度下降法实现一元线性回归 实验目的 本次实验旨在通过手动实现梯度下降法和随机梯度下降法来解决一元线性回归问题。具体目标包括:生成训练数据集,并使用matplotlib进行可视化。 设计一个`LinearModel`类…

[JavaScript] 事件委托以及 Vue 列表循环事件绑定的性能优化

前言 事件委托(Event Delegation) 是一种通过将事件监听器绑定到父元素,而不是直接绑定到每个子元素上的技术。这样可以减少事件监听器的数量,提升性能,并使得对动态添加或移除的元素更容易进行事件处理。 事件冒泡和事件捕获 事件冒泡:从里往外 <div id="parent…

GT收发器

1.GT触发器的IP使用 第一页 第二页 第三页 GTP IP 提供了两种解决跨时钟域的方法:(1)RX Elastic Buffer(RX 弹性缓冲器);(2)RX Phase Alignment(RX 相位对齐电路),两种方法的比较:RXElastic Buffer优点在于稳定,易使用, 执行相位校准的速度快,但是需要时钟和通道进…

Qt 中实现异步散列器

在很多工作中,我们需要计算数据或者文件的散列值,例如登录或下载文件。 而在 Qt 中,负责这项工作的类为 `QCryptographicHash`。 虽然 `QCryptographicHash `很优秀,但它最大的问题在于其散列值的计算是同步的( 即阻塞 ),对小数据来说并没什么影响,但对大数据来说则意味明…

新建工程——STM32学习笔记2

目录新建工程 添加启动程序Start 添加内核程序Core相关资料下载 下载链接(来自B站江协科技) 通过百度网盘分享的文件:STM32入门教程资料 链接:https://pan.baidu.com/s/17_sbwMXU-xBVFA2sK0smrg?pwd=cgn6 提取码:cgn6STM32开发方式有3种,分别是基于寄存器开发、基于标准…

Java八股复习指南-集合

Java集合 Map HashMap 实现原理/底层 Java1.8之前:数组加链表 Java1.8之后:当一个链表的长度超过8,且数组大小超过64时,会将链表转换成红黑树存储,查找效率更高,时间复杂度O(log n)。如果长度超过8,但是数组容量不足64,则会选择扩容数组。 定位算法 计算key的哈希值,并…

幂函数与指数函数区别

本文来自博客园,作者:cytlz2730,转载请注明原文链接:https://www.cnblogs.com/cytwjyy/p/18407701