JS性能优化之减少回流重绘次数

  1. 重绘 - Repaint
    当render tree中的一部分元素的样式改变(宽高、大小、位置等不变)导致页面重建
    如:color backgroundColor visibility…
    每个页面至少需要一次回流,就是在页面第一次加载的时候
  2. 回流 - Reflow
    元素的大小或者位置发生了变化(当页面布局和几何信息发生变化的时候),触发了重新布局导致渲染树重新计算布局和渲染

如: 删除可见的DOM元素;元素的位置大小/尺寸变化;内容变化;页面初始渲染;浏览器窗口视图

回流一定会触发重绘,而重绘不一定触发回流

  1. 性能优化 - 减少回流重绘次数
  • 放弃传统操作DOM的时代,基于Vue/React开发 mvvm / mvc / virtual / dom/ dom diff…
  • 分离读写
    现代浏览器都有渲染队列机制(遇到修改样式的代码后不会立刻渲染,而是添加到队列中,等到下一行是非修改样式代码再去将队列中的修改一起执行)
// 错误写法 会导致2次回流
let box = document.getElementById("box")
box.style.width = "200px"
console.log(box.clientWidth)
box.style.height = "200px"

// 正确写法 执行1次回流
let box = document.getElementById("box")
box.style.width = "200px"
box.style.height = "200px"
console.log(box.clientWidth)
  • 集中样式更改

创建样式类,为dom动态添加类

  • 缓存处理
// 错误 回流2次
box.style.width = box.clientWidth + "200px"
box.style.height = box.clientHeight + "300px"
// 正确 回流1次
let a = box.clientWidth
let b = box.clientHeight
box.style.width = a + "200px"
box.style.height = b + "300px"
  • 元素批量修改
  // 错误 引发5次回流
    for(let i=0; i<5; i++)
    {
        let li = document.createElement("li")
        li.innerHTML = i
        box.appendChild(li)
    }
    // 正确 引发1次回流
    // 1.文档碎片
    let frg = document.createDocumentFragment()
    for(let i=0; i<5; i++){
        let li = document.createElement("li")
        li.innerHTML = i
        frg.appendChild(li)
    }
    box.appendChild(frg)
    frg = null
    // 2.字符串拼接
    let str = ``
    for(let i=0; i<5; i++){
        str += `<li>${i}</li>`
    }
    box.innerHTML = str
  • 动画效果应用到position属性为absolute / fixed 的元素上(脱离文档流) CSS3 硬件加速(GPU加速)
  • transform / opacity / filters 等等会触发硬件加速,不会引发重绘和回流 牺牲平滑换取速度
  • 比如有个动画是每秒移动1个像素点,改为移动10个像素点 避免 table 布局和使用 css 的javascript

猜你喜欢

转载自blog.csdn.net/weixin_45959504/article/details/105893810