学习笔记——重排和重绘

为什么要减少重排和重绘,因为能提高性能

主要概念:

DOM树:表示页面结构,即页面都由那些DOM节点构成

渲染树:规定DOM节点如何显示

重排:当DOM的变化影响了元素的几何属性(宽或高),浏览器需要重新计算元素的几何属性,同样其他元素的几何属性和位置也会因此受到影响。浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树;

重绘:完成重排后,浏览器会重新绘制受影响的部分到屏幕

重排必定会引发重绘,但重绘不一定会引发重排

为什么操作DOM会很慢:

虽然DOM是由JavaScript实现的,但是在浏览器中都是把DOM和JavaScript分开来实现的,比如IE中,JavaScript的实现名为JScript,放在jscript.dll文件中,而DOM则放在另一个叫做mshtml.dll的库中。在Safari中,DOM和渲染是使用Webkit中的WebCore实现,而JavaScript是由独立的JavaScriptCore引擎实现,同样在Chrome中,同样是使用WebCore来实现渲染,而JavaScript引擎则是他们自己研发的V8引擎。

由于DOM和JavaScript是被分开独立实现的,因此,每一次在通过js操作DOM的时候,就需要先去连接js和DOM,我们可以这样理解:把DOM和JavaScript比作两个岛,他们之间通过一个收费的桥连接着,每一次访问DOM的时候,就需要经过这座桥,并且给“过路费”,访问的次数越多,路费就会越高,并且访问到DOM后,操作具体的DOM还需要给“操作费”,由于浏览器访问DOM的操作很多,因此,“路费”和“操作费”自然会增加,这就是为什么操作DOM会很慢的原因

何时触发:

  1. 页面渲染初始化;(无法避免)
  2. 添加或删除可见的DOM元素;
  3. 元素位置的改变,或者使用动画;
  4. 元素尺寸的改变——大小,外边距,边框;
  5. 浏览器窗口尺寸的变化(resize事件发生时);
  6. 填充内容的改变,比如文本的改变或图片大小改变而引起的计算值宽度和高度的改变;
  7. 获取布局信息的操作会导致队列刷新,比如:
  • offsetTop, offsetLeft, offsetWidth, offsetHeightscrollTop;
  • scrollLeft, scrollWidth, scrollHeightclientTop;
  • clientLeft, clientWidth, clientHeight;
  • getComputedStyle() (currentStyle in IE)

如何减少重排和重绘:

  • 尽量不要在布局信息改变时做查询(会导致渲染队列强制刷新),如果一定要查询,可以利用缓存。将访问的值存储起来,接下来使用就不会再引发回流;
  • 同一个DOM的多个属性改变可以写在一起(减少DOM访问,同时把强制渲染队列刷新的风险降为0)
  • 如果要批量添加DOM,可以先让元素脱离文档流,操作完后再带入文档流,这样只会触发一次重排(fragment元素的应用)
  • 将需要多次重排的元素,position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位。
  • 我们可以合并多次的DOM和样式的修改。并减少对style样式的请求,例如直接改变元素的className
  • display:none;先设置元素为display:none;然后进行页面布局等操作;设置完成后将元素设置为display:block;这样的话就只引发两次重绘和重排;
  • 使用cloneNode(true or false) 和 replaceChild 技术,引发一次回流和重绘;
  • 尽量不要使用table布局

减少DOM操作

  • 最小化DOM访问次数,尽量缓存访问DOM的样式信息,避免过度触发回流。
  • 如果在一个局部方法中需要多次访问同一个dom,则先暂存它的引用。
  • 采用更优的API替代消费高的api,转换优化消费高的集合
  • 用querySelectorAll()替代getElementByXX()。
  • 开启动画的GPU加速,把渲染计算交给GPU。
  • 少用HTML集合(类数组)来遍历,因为集合遍历比真数组遍历耗费更高。
  • 用事件委托来减少事件处理器的数量。

减少重排

  • 避免设置大量的style属性,因为通过设置style属性改变结点样式的话,每一次设置都会触发一次reflow,所以最好是使用class属性
  • 实现元素的动画,它的position属性,最好是设为absoulte或fixed,这样不会影响其他元素的布局
  • 动画实现的速度的选择。比如实现一个动画,以1个像素为单位移动这样最平滑,但是reflow就会过于频繁,大量消耗CPU资源,如果以3个像素为单位移动则会好很多。
  • 不要使用table布局,因为table中某个元素旦触发了reflow,那么整个table的元素都会触发reflow。那么在不得已使用table的场合,可以设置table-layout:auto;或者是table-layout:fixed这样可以让table一行一行的渲染,这种做法也是为了限制reflow的影响范围

css及动画处理

  • 少用css表达式
  • 减少通过JavaScript代码修改元素样式,尽量使用修改class名方式操作样式或动画;
  • 动画尽量使用在绝对定位或固定定位的元素上;
  • 隐藏在屏幕外,或在页面滚动时,尽量停止动画;

注意:table及其内部元素可能需要多次计算才能确定好其在渲染树中节点的属性值,比同等元素要多花两倍时间,这就是我们尽量避免使用table布局页面的原因之一。

参考:

https://www.imooc.com/article/45936

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值