17、重绘、重排(回流)
- 先把dom节点生成dom树(解析dom)
- 生成cssom(解析css)
- 布局:构成渲染树render tree(从根节点递归,布局)
- 绘制:绘制div等到页面上
重绘(repaint):一个元素外观的改变所触发的浏览器的行为,浏览器会根据元素的新属性重新绘制,使元素呈现新外观
回流(重排、重构reflow):当渲染树的一部分因为元素的尺寸、布局、隐藏等改变而需要重新构建称之为重排
重绘和重排的关系:在重排的过程中,浏览器会使渲染树中收到影响的部分失效,并且重新去构造这部分渲染树,完成重排之后,浏览器会重新绘制受影响的部分到屏幕中,该部分称为重绘。
重排(回流)一定会重绘,但是重绘不一定会重排。(重排=>布局 重绘=>样式)
触发重排的条件
- 页面渲染初始化
- 添加删除可见dom元素
- 元素位置改变或者使用动画
- 元素尺寸的改变——大小、外边距、边框
- 浏览器窗口尺寸的变化(resize事件发生时)
- 填充内容的改变,比如文本的改变导致的计算值的宽高改变
- 读取某些元素属性(读取宽高offsetTop/Top/Height/width等)
重绘或者重排的代价:耗时、导致浏览器卡顿
重绘重排优化
- 浏览器自己的优化:浏览器会维护一个队列,把所有会引起重绘或者重排的操作放入这个队列,等队列中的操作到了一定的哦时间间隔或者一定数量的时候,浏览器就会flush队列进行一个个处理,这样就会让多次回流和重绘便车个一次
- 我们也可以合并多次对dom的操作以及对样式的修改为一次,并且减少对style的样式请求
- 直接改变元素的className
- 先设置元素的
display:none
然后进行页面布局等操作,设置完成之后再将display:block
这样的话就之后出现两次重绘和重排 - 使用cloneNode(ture or false)和replace技术只引发一次重绘和重排
- 将需要毒刺重排的元素的
position
设置成absolte或者fixed,使其脱离文档流,那么它的变化不会影响到其他元素 - 如果要插入多个dom节点可以创建一个documentFragment创建完成之后一次性加入document
var fragment = document.createDocumentFragment()
for(let i = 0;i<=1000;i++){
var li = document.createElement('i')
li.innerHTML = i + '</br>'
fragment.append(li)
}
document.getElementById('container').appendChild(fragment)