本人已参与「新人创作礼」活动,一起开启掘金创作之路。
对于dom上的性能优化追根揭底是对重绘和节流的把控。
重绘:DOM节点元素没有删除,增加,移动,尺寸改变的情况,元素只有样式上的改变。浏览器针对这个样式改变对视图进行一个重新绘制。这个过程,叫做重绘。比如color,background的改变。就是典型的重绘。
回流:回流也叫做重排,指DOM节点元素出现删除,增加,移动,尺寸改变的情况。浏览器需要针对元素进行重新构建和渲染。这个过程被称为回流。
浏览器在接收到一个html文档的时候,会同时构建DOM节点树和CSS渲染树。注意,出于对浏览器性能上的考虑,浏览器并不会等待DOM节点树构建完毕后再去构建CSS渲染树,所以DOM节点树的构建和CSS渲染树的构建是同步的。
浏览器绘制流程如下
在这个过程中,如果在DOM节点树中扫描到JS代码,DOM节点树和CSS渲染树会停止构建,浏览器把控制权交给javascript的引擎。并且等待这一段JS代码运行完毕后再继续构建(因为浏览器不知道js代码是否会对后续的节点进行操作,万一那段JS代码是把dom即将构建的节点删掉咋办,那就白建了。所以需要等待混在dom中的js代码执行完毕之后再进行构建)。
重绘不一定会导致回流。但是回流一定需要重绘。而且,回流的性能消耗远大于重绘。
为了让重绘和回流的影响对我们的产品影响降低到最小,vue,react,angular等框架都使用了虚拟dom技术,就是避免浏览器进行不必要的重绘和回流。
重绘的触发场景↓
回流的触发场景↓
当我们需要动态改变某一个元素的位置的时候,不要使用position,使用translate,两种功能都可以实现元素的位移,但是position会触发回流,但是translate只会触发重绘。
尽量不要使用table布局,因为table中某一个小小的改动就会导致整个table进行重新布局。而且table的重新构建往往是其他元素的几倍。
避免频繁获取节点或者某一个会导致回流的元素。(例如 element.offsetLeft,document.getElementById)仅仅是读取这个元素就会导致回流,所以,条件允许的话,读取一次就缓存起来。避免多次读取。
可以使用css预先构建好的样式不要使用js去动态添加。
再translate无法满足元素移动需求的情况下,让元的position变成absolute或者fixed也就是脱离文档流之后再去移动,否则像relative此类状态去移动的话会导致后续全部元素陷入高频的回流状态。
需要隐藏元素的时候使用visibility:hidden而非display:none.display:none会导致回流但是visibility:hidden不会
离线操作:对dom进行操作的时候,可以先使用diaply:none将元素离线,操作完成以后再display:block显示。
....
在线客服
电话咨询
官方微信
返回顶部