一、重绘与回流
- 重绘(repaint):当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新,此时由于只需要 UI 层面的重新像素绘制,因此损耗较少。
常见的重绘操作:
1.改变元素颜色
2.改变元素背景色
3.more… - 回流(reflow):又叫重排(layout),类似于插队。当元素的尺寸、结构或者触发某些属性时,浏览器会重新渲染页面,称为回流。此时,浏览器需要重新经过计算,计算后还需要重新页面布局,因此是较重的操作。
常见的回流操作:
1.页面初次渲染
2.浏览器窗口大小改变
3.元素尺寸/位置/内容发生改变
4.元素字体大小变化
5.添加或者删除可见的 DOM 元素
6.激活 CSS 伪类(:hover……)
7.more ……
重点:
1.回流必定会触发重绘,重绘不一定会触发回流。重绘的开销较小,回流的代价较高。
2.重绘和回流都影响页面的响应速度
3.重绘和回流是无法避免的
4.重绘和回流这个问题只能优化,不能解决
5.任何的DOM操作都会引发回流
JavaScript避免回流的方法
- 避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。
- 避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。
- 也可以先为元素设置display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。
- 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
- 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流
注意:
display:none 不占位隐藏
overflow:hidden 占位隐藏
二、文档碎片
在浏览器中,修改、删除或者增加DOM元素。更新DOM会导致浏览器重新绘制屏幕,对于少量的更新,一条条循环插入也会运行很好。但是,如果当我们要向document中添加大量数据时(比如1w条),逐条添加节点,会导致reflow,这样会带来巨大的开销,这个过程就可能会十分缓慢。我们通常解决这种情况的办法尽量减少更新DOM,这也就意味着将DOM的改变分批处理,并在“活动”文档树之外执行这些更新。当需要创建一个相对比较大的子树,应该在子树完全创建之后再将子树添加到DOM树中,这时采用文档碎片技术来容纳所有的节点
含义:文档碎片document.createDocumentFragment() 是一个容器,用于暂时存放创建的dom元素
作用:将需要添加的大量元素先添加到文档碎片中,再将文档碎片添加到需要插入的位置,大大 减少dom操作,提高性能(IE和火狐比较明显)
比如需要往页面上放100个元素:
普通方式:(操作了100次dom)
for(var i = 0 ; i < 100 ; i++){
var oP = document.createElement('p') ;
oP.innerHTML = i ;
//DOM操作了100次
document.body.appendChild(oP) ;
文档碎片:(操作1次dom)
var fragment = document.createDocumentFragment() ;
console.log(fragment) ;
for(var i = 0 ; i < 100 ; i++){
//创建标签
var oP = document.createElement('p') ;
//把i放入到标签中去
oP.innerHTML = i ;
//把op添加到到文档碎片中去
fragment.appendChild(oP) ;
}
//最后放入到页面上
document.body.appendChild(fragment) ;
文章评论