最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

瀏覽器渲染原理_html/css_WEB-ITnose

來源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 16:17:21
文檔

瀏覽器渲染原理_html/css_WEB-ITnose

瀏覽器渲染原理_html/css_WEB-ITnose:瀏覽器工作大致流程 廢話少說,先來看個(gè)圖: 從上面這個(gè)圖中,我們可以看到那么幾個(gè)事: 1)瀏覽器會解析三個(gè)東西: 一個(gè)是HTML/SVG/XHTML,事實(shí)上,Webkit有三個(gè)C++的類對應(yīng)這三類文檔。解析這三種文件會產(chǎn)生一個(gè)DOM Tree。 CSS,解析CSS會產(chǎn)生
推薦度:
導(dǎo)讀瀏覽器渲染原理_html/css_WEB-ITnose:瀏覽器工作大致流程 廢話少說,先來看個(gè)圖: 從上面這個(gè)圖中,我們可以看到那么幾個(gè)事: 1)瀏覽器會解析三個(gè)東西: 一個(gè)是HTML/SVG/XHTML,事實(shí)上,Webkit有三個(gè)C++的類對應(yīng)這三類文檔。解析這三種文件會產(chǎn)生一個(gè)DOM Tree。 CSS,解析CSS會產(chǎn)生

瀏覽器工作大致流程

廢話少說,先來看個(gè)圖:

從上面這個(gè)圖中,我們可以看到那么幾個(gè)事:

1)瀏覽器會解析三個(gè)東西:

一個(gè)是HTML/SVG/XHTML,事實(shí)上,Webkit有三個(gè)C++的類對應(yīng)這三類文檔。解析這三種文件會產(chǎn)生一個(gè)DOM Tree。 CSS,解析CSS會產(chǎn)生CSS規(guī)則樹。 Javascript,腳本,主要是通過DOM API和CSSOM API來操作DOM Tree和CSS Rule Tree.

2)解析完成后,瀏覽器引擎會通過DOM Tree 和 CSS Rule Tree 來構(gòu)造 Rendering Tree。注意:

Rendering Tree 渲染樹并不等同于DOM樹,因?yàn)橐恍┫馠eader或display:none的東西就沒必要放在渲染樹中了。 CSS 的 Rule Tree主要是為了完成匹配并把CSS Rule附加上Rendering Tree上的每個(gè)Element。也就是DOM結(jié)點(diǎn)。也就是所謂的Frame。 然后,計(jì)算每個(gè)Frame(也就是每個(gè)Element)的位置,這又叫l(wèi)ayout和reflow過程。

3)最后通過調(diào)用操作系統(tǒng)Native GUI的API繪制。

DOM解析 HTML的DOM Tree解析如下:

 Web page parsing 

Web page parsing

This is an example Web page.

上面這段HTML會解析成這樣:

CSS解析

CSS的解析大概是下面這個(gè)樣子(下面主要說的是Gecko也就是Firefox的玩法),假設(shè)我們有下面的HTML文檔:

A few quotes Franklin said that "A penny saved is a penny earned." FDR said "We have nothing to fear but fear itself."

于是DOM Tree是這個(gè)樣子:

然后我們的CSS文檔是這樣的:

 /* rule 1 */ doc { display: block; text-indent: 1em; }/* rule 2 */ title { display: block; font-size: 3em; }/* rule 3 */ para { display: block; }/* rule 4 */ [class="emph"] { font-style: italic; }

于是我們的CSS Rule Tree會是這個(gè)樣子:

注意,圖中的第4條規(guī)則出現(xiàn)了兩次,一次是獨(dú)立的,一次是在規(guī)則3的子結(jié)點(diǎn)。所以,我們可以知道,建立CSS Rule Tree是需要比照著DOM Tree來的。CSS匹配DOM Tree主要是從右到左解析CSS的Selector,好多人以為這個(gè)事會比較快,其實(shí)并不一定。關(guān)鍵還看我們的CSS的Selector怎么寫了。

注意:CSS匹配HTML元素是一個(gè)相當(dāng)復(fù)雜和有性能問題的事情。所以,你就會在N多地方看到很多人都告訴你,DOM樹要小,CSS盡量用id和class,千萬不要過渡層疊下去,……

通過這兩個(gè)樹,我們可以得到一個(gè)叫Style Context Tree,也就是下面這樣(把CSS Rule結(jié)點(diǎn)Attach到DOM Tree上):

所以,F(xiàn)irefox基本上來說是通過CSS 解析 生成 CSS Rule Tree,然后,通過比對DOM生成Style Context Tree,然后Firefox通過把Style Context Tree和其Render Tree(Frame Tree)關(guān)聯(lián)上,就完成了。注意:Render Tree會把一些不可見的結(jié)點(diǎn)去除掉。而Firefox中所謂的Frame就是一個(gè)DOM結(jié)點(diǎn),不要被其名字所迷惑了。

注:Webkit不像Firefox要用兩個(gè)樹來干這個(gè),Webkit也有Style對象,它直接把這個(gè)Style對象存在了相應(yīng)的DOM結(jié)點(diǎn)上了。

渲染

渲染的流程基本上如下(黃色的四個(gè)步驟):

  • 計(jì)算CSS樣式
  • 構(gòu)建Render Tree
  • Layout – 定位坐標(biāo)和大小,是否換行,各種position, overflow, z-index屬性 ……
  • 正式開畫
  • 注意:上圖流程中有很多連接線,這表示了Javascript動態(tài)修改了DOM屬性或是CSS屬會導(dǎo)致重新Layout,有些改變不會,就是那些指到天上的箭頭,比如,修改后的CSS rule沒有被匹配到,等。

    這里重要要說兩個(gè)概念,一個(gè)是Reflow,另一個(gè)是Repaint。這兩個(gè)不是一回事。

  • Repaint ——屏幕的一部分要重畫,比如某個(gè)CSS的背景色變了。但是元素的幾何尺寸沒有變。
  • Reflow ——意味著元件的幾何尺寸變了,我們需要重新驗(yàn)證并計(jì)算Render Tree。是Render Tree的一部分或全部發(fā)生了變化。這就是Reflow,或是Layout。(HTML使用的是flow based layout,也就是流式布局,所以,如果某元件的幾何尺寸發(fā)生了變化,需要重新布局,也就叫reflow)reflow 會從這個(gè)root frame開始遞歸往下,依次計(jì)算所有的結(jié)點(diǎn)幾何尺寸和位置,在reflow過程中,可能會增加一些frame,比如一個(gè)文本字符串必需被包裝起來。
  • Reflow的成本比Repaint的成本高得多的多。DOM Tree里的每個(gè)結(jié)點(diǎn)都會有reflow方法,一個(gè)結(jié)點(diǎn)的reflow很有可能導(dǎo)致子結(jié)點(diǎn),甚至父點(diǎn)以及同級結(jié)點(diǎn)的reflow。在一些高性能的電腦上也許還沒什么,但是如果reflow發(fā)生在手機(jī)上,那么這個(gè)過程是非常痛苦和耗電的。 所以,下面這些動作有很大可能會是成本比較高的。

  • 當(dāng)你增加、刪除、修改DOM結(jié)點(diǎn)時(shí),會導(dǎo)致Reflow或Repaint
  • 當(dāng)你移動DOM的位置,或是搞個(gè)動畫的時(shí)候。
  • 當(dāng)你修改CSS樣式的時(shí)候。
  • 當(dāng)你Resize窗口的時(shí)候(移動端沒有這個(gè)問題),或是滾動的時(shí)候。
  • 當(dāng)你修改網(wǎng)頁的默認(rèn)字體時(shí)。
  • 注:display:none會觸發(fā)reflow,而visibility:hidden只會觸發(fā)repaint,因?yàn)闆]有發(fā)現(xiàn)位置變化。
  • 多說兩句關(guān)于滾屏的事,通常來說,如果在滾屏的時(shí)候,我們的頁面上的所有的像素都會跟著滾動,那么性能上沒什么問題,因?yàn)槲覀兊娘@卡對于這種把全屏像素往上往下移的算法是很快。但是如果你有一個(gè)fixed的背景圖,或是有些Element不跟著滾動,有些Elment是動畫,那么這個(gè)滾動的動作對于瀏覽器來說會是相當(dāng)相當(dāng)痛苦的一個(gè)過程。你可以看到很多這樣的網(wǎng)頁在滾動的時(shí)候性能有多差。因?yàn)闈L屏也有可能會造成reflow。

    基本上來說,reflow有如下的幾個(gè)原因:

  • Initial。網(wǎng)頁初始化的時(shí)候。
  • Incremental。一些Javascript在操作DOM Tree時(shí)。
  • Resize。其些元件的尺寸變了。
  • StyleChange。如果CSS的屬性發(fā)生變化了。
  • Dirty。幾個(gè)Incremental的reflow發(fā)生在同一個(gè)frame的子樹上。
  • 好了,我們來看一個(gè)示例吧:

    var bstyle = document.body.style; // cachebstyle.padding = "20px"; // reflow, repaintbstyle.border = "10px solid red"; // 再一次的 reflow 和 repaintbstyle.color = "blue"; // repaintbstyle.backgroundColor = "#fad"; // repaintbstyle.fontSize = "2em"; // reflow, repaint// new DOM element - reflow, repaintdocument.body.appendChild(document.createTextNode('dude!'));

    當(dāng)然,我們的瀏覽器是聰明的,它不會像上面那樣,你每改一次樣式,它就reflow或repaint一次。一般來說,瀏覽器會把這樣的操作積攢一批,然后做一次reflow,這又叫異步reflow或增量異步reflow。但是有些情況瀏覽器是不會這么做的,比如:resize窗口,改變了頁面默認(rèn)的字體,等。對于這些操作,瀏覽器會馬上進(jìn)行reflow。

    但是有些時(shí)候,我們的腳本會阻止瀏覽器這么干,比如:如果我們請求下面的一些DOM值:

    offsetTop, offsetLeft, offsetWidth, offsetHeightscrollTop/Left/Width/HeightclientTop/Left/Width/HeightIE中的 getComputedStyle(), 或 currentStyle

    因?yàn)椋绻覀兊某绦蛐枰@些值,那么瀏覽器需要返回最新的值,而這樣一樣會flush出去一些樣式的改變,從而造成頻繁的reflow/repaint。

    減少reflow/repaint

    下面是一些Best Practices:

    1)不要一條一條地修改DOM的樣式。與其這樣,還不如預(yù)先定義好css的class,然后修改DOM的className。

    // badvar left = 10,top = 10;el.style.left = left + "px";el.style.top = top + "px";// Goodel.className += " theclassname";// Goodel.style.cssText += "; left: " + left + "px; top: " + top + "px;";

    2)把DOM離線后修改。如:

    使用documentFragment 對象在內(nèi)存里操作DOM 先把DOM給display:none(有一次reflow),然后你想怎么改就怎么改。比如修改100次,然后再把他顯示出來。 clone一個(gè)DOM結(jié)點(diǎn)到內(nèi)存里,然后想怎么改就怎么改,改完后,和在線的那個(gè)的交換一下。

    3)不要把DOM結(jié)點(diǎn)的屬性值放在一個(gè)循環(huán)里當(dāng)成循環(huán)里的變量。不然這會導(dǎo)致大量地讀寫這個(gè)結(jié)點(diǎn)的屬性。

    4)盡可能的修改層級比較低的DOM。當(dāng)然,改變層級比較底的DOM有可能會造成大面積的reflow,但是也可能影響范圍很小。

    5)為動畫的HTML元件使用fixed或absoult的position,那么修改他們的CSS是不會reflow的。

    6)千萬不要使用table布局。因?yàn)榭赡芎苄〉囊粋€(gè)小改動會造成整個(gè)table的重新布局。

    幾個(gè)工具和幾篇文章

    有時(shí)候,你會也許會發(fā)現(xiàn)在IE下,你不知道你修改了什么東西,結(jié)果CPU一下子就上去了到100%,然后過了好幾秒鐘repaint/reflow才完成,這種事情以IE的年代時(shí)經(jīng)常發(fā)生。所以,我們需要一些工具幫我們看看我們的代碼里有沒有什么不合適的東西。

    Chrome下,Google的SpeedTracer是個(gè)非常強(qiáng)悍的工作讓你看看你的瀏覽渲染的成本有多大。其實(shí)Safari和Chrome都可以使用開發(fā)者工具里的一個(gè)Timeline的東東。 Firefox下這個(gè)基于Firebug的叫Firebug Paint Events的插件也不錯(cuò)。 IE下你可以用一個(gè)叫dynaTrace的IE擴(kuò)展。 最后,別忘了下面這幾篇提高瀏覽器性能的文章:

    聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    瀏覽器渲染原理_html/css_WEB-ITnose

    瀏覽器渲染原理_html/css_WEB-ITnose:瀏覽器工作大致流程 廢話少說,先來看個(gè)圖: 從上面這個(gè)圖中,我們可以看到那么幾個(gè)事: 1)瀏覽器會解析三個(gè)東西: 一個(gè)是HTML/SVG/XHTML,事實(shí)上,Webkit有三個(gè)C++的類對應(yīng)這三類文檔。解析這三種文件會產(chǎn)生一個(gè)DOM Tree。 CSS,解析CSS會產(chǎn)生
    推薦度:
    標(biāo)簽: 瀏覽器 原理 html
    • 熱門焦點(diǎn)

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top