简单介绍
- 网页生成布局(重排 reflow),页面绘制(重绘 repaint)一个个盒子元素
重排一定会引起重绘,重绘不一定引起重排
- 为什么这样说,如果我改变了布局,比如改变边框宽度或者给段落增加文字,浏览器需要重新计算元素的几何属性,就会重排,然后就会重新绘制
- 但是如果改变元素的背景色,就只会发生重绘,而不会影响布局
- 重绘和重排非常消耗资源,应该尽量避免
怎样优化
批量读或者批量写
现代浏览器已经很智能,会把所有变动排在一起,然后一次性集中在一起,推入到一个队列然后再渲染,这样通过队列话修改然后批量执行可以优化重排过程。
1 | div.stryle.color = "red"; |
- 由上可知,如果我们在写操作之后,再读会立即渲染,有以下读操作
1 | offsetTop / offsetLeft / offsetWidth / offsetHeight; |
- 所以我们要懂得批量读和批量写
1 | // bad |
合并样式操作
尽管现代浏览器做了优化,但是旧的浏览器可能没有,所以我们应该尽可能合并对样式的修改
- cssText:el.style.cssText=’border-left: 1px; border-right: 2px; padding: 5px;’
- 修改 className:如果不是那么依赖计算,可以通过修改 className
修改 dom 元素的时候使其脱离文档流
当我们需要对 dom 元素频繁操作的时候,我们可以这样减少重排和重绘
- 让该 dom 元素脱离文档流(重排)
- 操作元素
- 完成后再添加到 document(重排)
如何脱离文档流
- 隐藏元素:display:none,然后一系列操作后,再显示
- 推荐:使用 document fragment,就是传说中的文档碎片了,document.createDocumentFragment(),另外的 dom 子树,操作完后,再拷贝回来文档中,div.appendChild(fragment)
- 将原始元素拷贝到一个脱离文档的节点中,cloneNode,修改这个副本,然后再通过这个元素的父元素的 replaceChild 替换他
1 | let old = document.getElementById("mylist"); |
缓存读过的样式结果
- div.style.top 读取可能会重排,这样最好这个缓存到变量里面,下次要用到这个就不用再读 div 的信息了
定位脱离文档流
- 可以将要多次重排的元素,position 可以设置 abs 和 fixed,这样就脱离文档流,不会影响其他元素。
- 有动画效果的可以设置为绝对定位