DOM操作耗时
深入了解DOM,如何高效的操作DOM
线程切换
浏览器包括渲染引擎(也称浏览器内核)和javascript引擎,它们都是单线程运行。
单线程的优势是开发方便,避免多线程下的死锁、竞争等问题,劣势是失去了并发能力
浏览器为了避免两个引擎同时修改页面而造成渲染结果不一致的情况,增加了另外一个机制,这两个引擎具有互斥性,也就是说在某个时刻只有一个引擎在运行,另一个引擎会被阻塞。操作系统在进行线程切换的时候需要保存上一个线程执行时的状态信息并读取下一个线程的状态信息,俗称上下文切换,这个操作相对而言是比较耗时的。
每次操作DOM就会引发线程的上下文切换——从Javascript引擎切换到渲染引擎执行对应操作,再切换回Javascript引擎继续执行,这就带来了性能损耗,单次切换的消耗的时间是非常少的,但是如果频繁地大量切换,那么就会产生性能问题
建议把需要操作的DOM进行缓存,即赋值给变量,操作变量
重新渲染
渲染过程中最耗时的两个步骤为 重排(Reflow)与 重绘(Repaint)
浏览器在渲染页面时会将 HTML 和 CSS 分别解析成 DOM 树和 CSSOM 树,然后合并进行排布,再绘制成我们可见的页面。如果在操作 DOM 时涉及到元素、样式的修改,就会引起渲染引擎重新计算样式生成 CSSOM 树,同时还有可能触发对元素的重新排布(简称“重排”)和重新绘制(简称“重绘”)。
-
可能会影响到其他元素排布的操作就会引起重排,继而引发重绘,比如:
-
修改元素边距、大小
-
添加、删除元素
-
改变窗口大小
-
-
与之相反的操作则只会引起重绘,比如:
-
设置背景图片
-
修改字体颜色
-
改变 visibility 属性值
-
总结
- 尽量不要使用复杂的匹配规则和复杂的样式,从而减少渲染引擎计算样式规则生成CSSDOM树的时间
- 尽量减少重排和重绘影响的区域
- 使用CSS3特性来实现动画效果