JS 优化之 document.Documentfragment 片段

我们先简单介绍下 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属性为absolutefixed的元素,回流的开销会比较小,因为不用考虑它对其他元素的影响。
  • 10. 只在必要的时候,才将元素的display属性为可见,因为不可见的元素不影响回流和重绘。另外,visibility: hidden 的元素只对重绘有影响,不影响回流。
  • 11. 一些 js 导致的页面回流操作可以放在 window.requestAnimationFrame() 帧动画中执行

!!!备注:

** reflow 回流中,改动元素的位置/大小等信息,会触发异步统一合并更新,所以,有时候先更改width,再获取offsetWidth/clientWidth还是之前的,就是因为他还没有更新**

猜你喜欢

转载自blog.csdn.net/Vue2018/article/details/129983640