浏览器是如何渲染页面的?
a.解析HTML文件,创建DOM树。自上而下,遇到任何样式(link、style)与脚本(script)都会阻塞(外部样式不阻塞后续外部脚本的加载);
b.解析CSS。优先级:浏览器默认设置<用户设置<外部样式<内联样式<HTML中的style样式;
c.将CSS与DOM合并,构建渲染树(Render Tree);
d.布局和绘制,重绘(repaint)和重排(reflow)。
-----------------------------------------------------------------------
渲染引擎在取得内容之后的基本流程:
解析HTML构建dom树—>构建render树—>布局render树—>绘制页面。
1、构建dom树 HTML文档中的所有内容都是节点,各节点之间拥有层级关系,如父子关系,兄弟关系等等,彼此相连构成dom树,dom树中节点和HTML文档存在一一对应的关系。
需要注意的是:在构建dom树期间,如果遇到JS,会阻塞dom树的构建,优先加载JS文件,加载完毕后在继续构建dom树。
在构建dom树的同时,浏览器还会构建一个CSSOM。当遇到css文件时,先加载css文件,然后构建CSSOM,但是会阻塞render树的构建。如果将css文件放在底部,render树在之前就已经构建完了,因此用户可能会看到无样式的页面或者闪屏。
2、渲染树(render树) 渲染树又dom树和CSSOM构成,但并不是必须等dom树及CSSOM加载完成后才开始合并构建render树,三者的构建并无先后条件,亦非完全独立,因此会形成一边加载,一边解析,一边渲染的现象。构建render树,根据render树计算每个可见元素的布局,并输出到绘制流程上,将像素渲染到屏幕上。
3、布局render树 有了render树,浏览器已经能知道网页中有哪些节点,各个节点的css定义以及他们的从属关系,从而去计算出每个节点在屏幕中的位置。
4、绘制 绘制包括重绘和重排两个过程。
4.1、重绘:屏幕的一部分重绘,render树节点发生改变,但不影响该节点在页面中的空间位置及大小,比如说某个div标签的背景颜色、内容发生变化,但几何属性没有发生变化,此时就会触发浏览器重绘。触发重绘的操作主要有:vidibility、outline、背景色等属性的改变。
4.2、重排:也叫回流。当render树节点发生变化,影响了节点的几何属性,导致该节点的位置发生变化,此时就会导致浏览器需要重新布局,这个过程就叫做浏览器的重排。
需要注意的是:重排必将会引起重绘,而重绘不一定需要重排!触发重排的几何因素主要有以下几点:
4.2.1、页面第一次渲染。在页面发生首次渲染的时候,所有组件都要进行首次布局,这是开销最大的一次重排。
4.2.2、浏览器窗口尺寸改变。
4.2.3、元素位置和尺寸发生改变的时候。
4.2.4、新增和删除可见元素。
4.2.5、内容发生改变(文字数量或图片大小等等)。
4.2.6、元素字体大小变化。。
4.2.7、激活CSS伪类(例如::hover)。
4.2.8、设置style属性。
4.2.9、查询某些属性或调用某些方法。比如说:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight。除此之外,当我们调用getComputedStyle方法,或者IE里的currentStyle时,也会触发重排,原理是一样的,都为求一个“即时性”和“准确性”。
如何减少重绘和重排?
1、直接改变className。
2、让要操作的元素进行“离线处理”,处理完后一起更新。
3、不要经常访问会引起浏览器flash队列的属性,如果确实需要,可以利用缓存。
4、让元素脱离动画流,减少render树的规模。
相关推荐
Vue和React是数据驱动视图,如何有效控制DOM操作?能不能把计算,更多的转移为js计算?因为js执行速度很快。patch函数-->patch,对比tag,对比tag与key,对比children