我们先简单介绍下 document.Documentfragment 的作用,创建一个文档片段,这个片段存在内存中,而非真实的 DOM 节点,所以插入其子元素并不会触发页面回流/重绘,所以可以利用其连续创建多个 dom 节点
一、案例
之前的创建节点方式
let ul = document.getElementsByTagName('ul')[0]
for (let i = 0; i < 100; i++) {
let el = document.createElement('li')
el.innerHTML = i
ul.appendChild(el)
}
可以看下他的性能曲线,因为每一次的创建节点,都会触发主线程的 布局(Layout) 也就是回流操作,接着触发 重绘(Piant) 操作,也就是触发100次:

而用片段的这种方式创建,只会触发一次回流操作:
let ul = document.getElementsByTagName('ul')[0]
let frag = document.createDocumentFragment()
for (let i = 0; i < 100; i++) {
let el = document.createElement('li')
el.innerHTML = i
frag.appendChild(el)
}
ul.appendChild(frag)
性能分析:

可以对比看的出,紫色的区域 Rendering 也就是回流操作,明显用片段创建的时长更有优势
二、拓展
拓展一些关于优化渲染效率的方式:
- 1. 样式文件应当在
head标签中,而脚本文件在body结束前,这样可以防止阻塞的方式 - 2.
script脚本会阻塞主渲染线程,所以渲染不需要同步执行的可以放在渲染结束后加载,使用defer来控制脚本的加载时机 - 3. 简化并优化
CSS选择器,尽量将嵌套层减少到最小 - 4.
DOM的多个读操作(或多个写操作),应该放在一起。不要两个读操作之间,加入一个写操作。 - 5. 不要一条条地改变样式,而要通过改变
class,或者csstext属性,一次性地改变样式 - 6. 尽量用
transform来做形变和位移,因为此操作发生在合并线程中的画(Draw)操作,不会影响到主渲染线程 - 7. 尽量使用离线
DOM,而不是真实的网页DOM,来改变元素样式。比如,操作Document Fragment对象,完成后再把这个对象加入DOM - 8. 先将元素设为
display: none(需要1次回流和重绘),然后对这个节点进行100次操作,最后再恢复显示(需要1次回流和重绘)。这样一来,你就用两次重新渲染,取代了可能高达100次的重新渲染。 - 9.
position属性为absolute或fixed的元素,回流的开销会比较小,因为不用考虑它对其他元素的影响。 - 10. 只在必要的时候,才将元素的
display属性为可见,因为不可见的元素不影响回流和重绘。另外,visibility: hidden的元素只对重绘有影响,不影响回流。 - 11. 一些
js导致的页面回流操作可以放在window.requestAnimationFrame()帧动画中执行
!!!备注:
** reflow 回流中,改动元素的位置/大小等信息,会触发异步统一合并更新,所以,有时候先更改width,再获取offsetWidth/clientWidth还是之前的,就是因为他还没有更新**

文章介绍了DocumentFragment的作用,它能减少DOM操作引起的回流和重绘,提高性能。通过对比案例展示了使用DocumentFragment创建多个DOM节点的优势。此外,还列举了其他优化渲染效率的方法,如调整脚本加载时机,优化CSS选择器,以及使用requestAnimationFrame等策略。
352

被折叠的 条评论
为什么被折叠?



