首先,看一張圖片:
首先是解析:
1)這是一個解析的過程,瀏覽器會解析三個東西:
一個是HTML/SVG/XHTML,事實上,Webkit有三個C++的類對應這三類文檔。解析這三種文件會產生一個DOM Tree。 CSS,解析CSS會產生CSS規則樹。 Javascript,腳本,主要是通過DOM API和CSSOM API來操作DOM Tree和CSS Rule Tree.
2)解析完成后,瀏覽器引擎會通過DOM Tree 和 CSS Rule Tree 來構造 Rendering Tree。注意:Rendering Tree 渲染樹并不等同于DOM樹,因為一些像Header或display:none的東西就沒必要放在渲染樹中了。 CSS 的 Rule Tree主要是為了完成匹配并把CSS Rule附加上Rendering Tree上的每個Element。也就是DOM結點。也就是所謂的Frame。 然后,計算每個Frame(也就是每個Element)的位置,這又叫layout和reflow過程。
3)最后通過調用操作系統Native GUI的API繪制。
其次,就Firefox來說基本上就是通過CSS 解析 生成 CSS Rule Tree,然后,通過比對DOM生成Style Context Tree,然后Firefox通過把Style Context Tree和其Render Tree(Frame Tree)關聯上,就完成了。注意:Render Tree會把一些不可見的結點去除掉。而Firefox中所謂的Frame就是一個DOM結點,不要被其名字所迷惑了。
注:Webkit不像Firefox要用兩個樹來干這個,Webkit也有Style對象,它直接把這個Style對象存在了相應的DOM結點上了。
然后到了,渲染的步驟:
可以把瀏覽器當成一個畫板,它的繪畫又包含幾個步驟
1 . 計算CSS樣式
2 . 構建Render Tree
3 . Layout – 定位坐標和大小,是否換行,各種position, overflow, z-index屬性 ……
4 . 正式開畫
5 . 完成頁面展現.
當然這里還有兩個重要的內容,一個是Repaint另一個是Reflow:
- Repaint ——屏幕的一部分要重畫,比如某個CSS的背景色變了。但是元素的幾何尺寸沒有變。
- Reflow ——意味著元件的幾何尺寸變了,我們需要重新驗證并計算Render Tree。是Render Tree的一部分或全部發生了變化。這就是Reflow,或是Layout。(HTML使用的是flow based layout,也就是流式布局,所以,如果某元件的幾何尺寸發生了變化,需要重新布局,也就叫reflow)reflow 會從<html>這個root frame開始遞歸往下,依次計算所有的結點幾何尺寸和位置,在reflow過程中,可能會增加一些frame,比如一個文本字符串必需被包裝起來。
那哪些情況會觸發這些重繪或重構呢?
1 . 當你增加、刪除、修改DOM結點時,會導致Reflow或Repaint
2 . 當你移動DOM的位置,或是搞個動畫的時候。
3 . 當你修改CSS樣式的時候。
4 . 當你Resize窗口的時候(移動端沒有這個問題),或是滾動的時候。
5 .當你修改網頁的默認字體時。
注:display:none會觸發reflow,而visibility:hidden只會觸發repaint,因為沒有發現位置變化。
最后,Reflow的成本比Repaint的成本高得多的多。DOM Tree里的每個結點都會有reflow方法,一個結點的reflow很有可能導致子結點,甚至父點以及同級結點的reflow。在一些高性能的電腦上也許還沒什么,但是如果reflow發生在手機上,那么這個過程是非常痛苦和耗電的。