webkit 包含两部分引擎组件:WebCore 和 JavaScriptCore;
Safari,Amazon Kindle e-book reader,BlackBerry,Android(4.4之前) 使用的webkit;
Chrome 和 opera、Android(4.4开始)从2013年开始使用 Blink(webkit 的 webCore 和 JavaScript 引擎 V8);
浏览器引擎对比可参考 Comparison of web browser engines
浏览器对比参考 Comparison of web browsers
webkit一般性渲染过程
根据渲染引擎所提供的渲染网页的功能,主要分三层,最上层用虚线框住的是渲染引擎所提供的功能。
重绘和重排
- 重排(reflow):部分渲染树(或者整个渲染树)需要重新分析并且节点尺寸需要重新计算。至少会有一次重排-初始化页面布局。
- 重绘(repaint):节点的几何属性或者样式发生改变,例如改变元素背景色,屏幕上的部分内容需要更新。
什么情况会触发重排和重绘?
以下三种情况,会导致网页重新渲染,就需要重新生成布局和重新绘制。
- 添加、删除、更新DOM节点
- 通过
display: none
隐藏一个DOM节点-触发重排和重绘 - 通过
visibility: hidden
隐藏一个DOM节点-只触发重绘,因为没有几何变化 - 移动或者给页面中的DOM节点添加动画
- 添加一个样式表,调整样式属性
- 用户行为,例如调整窗口大小,改变字号,鼠标悬停、页面滚动、输入框键入文字。
样式的写操作之后,如果有下面这些属性的读操作,都会引发浏览器立即重新渲染。
offsetTop/offsetLeft/offsetWidth/offsetHeight
scrollTop/scrollLeft/scrollWidth/scrollHeight
clientTop/clientLeft/clientWidth/clientHeight
getComputedStyle()
所以,从性能角度考虑,尽量不要把读操作和写操作,放在一个语句里面。
一般的规则是: 样式表越简单,重排和重绘就越快。 重排和重绘的DOM元素层级越高,成本就越高。 table元素的重排和重绘成本,要高于div元素
第一条,DOM 的多个读操作(或多个写操作),应该放在一起。不要两个读操作之间,加入一个写操作。
第二条,如果某个样式是通过重排得到的,那么最好缓存结果。避免下一次用到的时候,浏览器又要重排。
第三条,不要一条条地改变样式,而要通过改变class,或者csstext属性,一次性地改变样式。
// bad
var left=10;
var top=10;
el.style.left= left+”px”;
el.style.top= top+”px”;
// good
el.className+=” theclassname”;
// good
el.style.cssText+=”;
left: “+ left+”px;
top: “+ top+”px;”;
第四条,尽量使用离线DOM,来改变元素样式。比如,操作Document Fragment对象,完成后再把这个对象加入DOM;使用 cloneNode() 方法,在克隆的节点上进行操作,然后再用克隆的节点替换原始节点。
第五条,先将元素设为 display: none (需要1次重排和重绘),然后对这个节点进行100次操作,最后再恢复显示(需要1次重排和重绘)。这样一来,你就用两次重新渲染,取代了可能高达100次的重新渲染。
第六条,position属性为absolute或fixed的元素,重排的开销会比较小,因为不用考虑它对其他元素的影响。
第七条,只在必要的时候,才将元素的display属性为可见,因为不可见的元素不影响重排和重绘。另外,visibility : hidden 的元素只对重排有影响,不影响重绘。
第八条,使用虚拟DOM的脚本库,比如React,Vue等。
第九条,使用 window.requestAnimationFrame()、window.requestIdleCallback() 这两个方法调节重新渲染。
参考:
http://zhangzhaoaaa.iteye.com/blog/2183520?utm_source=tuicool&utm_medium=referral
http://www.cnblogs.com/Chen-XiaoJun/p/6209821.html
http://www.jianshu.com/p/3259ed7f68e2
https://en.wikipedia.org/wiki/WebKit