公告

👇👇👇扫我

图片
Skip to content

重绘与回流

当界面发生更改的时候会触发重绘与回流

会导致回流的操作

页面首次渲染(无法避免且开销最大的一次) 浏览器窗口大小发生改变(resize 事件) -元素尺寸或位置发生改变(边距、宽高、边框等) 元素内容变化(文字数量或图片大小等等) 元素字体大小变化(font-size) 添加或者删除可见的 DOM 元素 激活 CSS 伪类(例如::hover) 查询某些属性或调用某些方法

如何减少回流(Reflow)与重绘(Repaint)?(优化)

  1. 如果需要对 DOM 进行多次访问,尽量使用局部变量缓存该 DOM

  2. 避免使用 table 布局,可能很⼩的⼀个⼩改动会造成整个 table 的重新布局

  3. CSS 选择符从右往左匹配查找,避免节点层级过多

  4. DOM 离线处理,减少回流重绘次数 display:none

离线的 DOM 不属于当前 DOM 树中的任何一部分,这也就意味着我们对离线 DOM 处理就不会引起页面的回流与重绘。

  1. 通过 documentFragment 创建一个 dom 文档片段,在它上面批量操作 dom,操作完成之后,再添加到文档中,这样只会触发一次重排。
js
const el = document.querySelector('.box')
const fruits = ['front', 'nanjiu', 'study', 'code']
const fragment = document.createDocumentFragment()
fruits.forEach((item) => {
  const li = document.createElement('li')
  li.innerHTML = item
  fragment.appendChild(li)
})
el.appendChild(fragment)
  1. 克隆节点,修改完再替换原始节点
js
const el = document.querySelector('.box')
const fruits = ['front', 'nanjiu', 'study', 'code']
const cloneEl = el.cloneNode(true)
fruits.forEach((item) => {
  const li = document.createElement('li')
  li.innerHTML = item
  cloneEl.appendChild(li)
})
el.parentElement.replaceChild(cloneEl, el)
  1. DOM 脱离普通文档流 使用 absoult 或 fixed 让元素脱离普通文档流,使用绝对定位会使的该元素单独成为渲染树中 body 的一个子元素,重排开销比较小,不会对其它节点造成太多影响。

  2. CSS3 硬件加速(GPU 加速) 使用 css3 硬件加速,可以让 transform、opacity、filters 这些动画不会引起回流重绘 。但是对于动画的其它属性,比如 background-color 这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能。

总结

  1. 界面布局发生变化触发回流

  2. 不影响布局的样式发生变化触发重绘

  3. 回流就是计算元素在设备内的确切位置和大小并且重新绘制

  4. 回流的代价要远大于重绘。并且回流必然会造成重绘,但重绘不一定会造成回流。

阅读量: 0
评论量: 0