ios移動網(wǎng)站開發(fā)詳解 pdf關(guān)鍵詞挖掘站網(wǎng)
一、瀏覽器是如何渲染頁面的
常見的簡潔答案:
- 瀏覽器內(nèi)核拿到內(nèi)容后,渲染流程大致如下:
- 解析HTML,構(gòu)建Dom樹;
- 解析CSS,構(gòu)建Render樹;(將CSS代碼解析成樹形的數(shù)據(jù)結(jié)構(gòu),與Dom樹結(jié)合形成Render樹)
- 布局Render樹(Layout/reflow),負責(zé)各元素尺寸、位置的計算;
- 繪制Render樹(painting),繪制頁面像素信息;
- 瀏覽器將各層的信息發(fā)送給GPU,GPU會將各層合成(composite),顯示在屏幕上
牛逼的震驚面試官的答案:
- 當(dāng)瀏覽器的網(wǎng)絡(luò)線程收到HTML文檔后,會產(chǎn)生一個渲染任務(wù),并將其傳遞給渲染主線程的消息隊列。在事件循環(huán)機制的作用下,渲染主線程取出消息隊列中的渲染任務(wù),開啟渲染流程。
- 整個渲染流程分為多個階段,分別是:HTML解析、樣式計算、布局、分層、繪制、分塊、光柵化、畫。每個階段都有明確的輸入和輸出,上一個階段的輸出會成為下一個階段的輸入,這樣整個渲染流程就形成了一套組織嚴(yán)密的生產(chǎn)流水線。
- 渲染的第一步是解析HTML:
- 解析過程中遇到CSS就解析CSS,遇到JS就解析JS。為了提高解析效率,瀏覽器在開始解析前,會啟動一個預(yù)解析的線程,率先下載HTML中的外部CSS文件和外部的JS文件
- 如果主線程解析到link位置,此時外部的CSS文件還沒有下載解析好,主線程不會等待,繼續(xù)解析后續(xù)的HTML。這是因為下載和解析CSS的工作是在預(yù)解析線程中進行的。這就是CSS不會阻塞HTML解析的根本原因。
- 如果主線程解析到script位置,會停止解析HTML,轉(zhuǎn)而等待JS文件下載好,并將全局代碼解析執(zhí)行完成后,才能繼續(xù)解析HTML。這是因為JS代碼執(zhí)行的過程可能會修改當(dāng)前的DOM樹,所以DOM樹的生成必須暫停。這就是JS會阻塞HTML解析的根本原因。
- 第一步完成后,會得到DOM樹和CSSOM樹,瀏覽器的默認樣式、內(nèi)部樣式、外部樣式、行內(nèi)樣式均會包含在CSSOM樹中。
- 渲染的下一步是樣式計算:
- 主線程會遍歷得到DOM樹,依次為樹中的每個節(jié)點計算出它最終的樣式,稱之為Computed Style。
- 在這一過程中,很多預(yù)設(shè)值會變成絕對值,比如red會變成rgb(255,0,0);相對單位會變成絕對單位,比如em會變成px。
- 這一步完成后,會得到一棵帶有樣式的DOM樹。
- 接下來是布局,布局完成后會得到布局樹:
- 布局階段會依次遍歷DOM樹的每一個節(jié)點,計算每個節(jié)點的幾何信息。例如節(jié)點的寬高、相對包含塊的位置。
- 大部分時候,DOM樹和布局樹并非一一對應(yīng)。比如display: none;的節(jié)點沒有幾何信息,因此不會生成到幾何樹;又比如使用了偽元素選擇器,雖然DOM樹中不存在這些偽元素節(jié)點,但他們擁有幾何信息,所以會生成到布局樹中。還有匿名行盒、匿名塊盒等等都會導(dǎo)致DOM樹和布局樹無法一一對應(yīng)。
- 下一步是分層:
- 主線程會使用一套復(fù)雜的策略對整個布局樹中進行分層。
- 分層的好處在于,將來某一個層改變后、僅會對該層進行后續(xù)處理,從而提升效率。
- 滾動條、折疊上下文、transform、opacity等樣式都會或多或少的影響分層效果,也可以通過will-change屬性更大程度的影響分層效果。
- 再下一步是繪制:
- 主線程會為每個層單獨繪制指令集,用于描述這一層的內(nèi)容該如何畫出來。
- 完成繪制后,主線程將每個圖層的繪制信息提交給合成線程,剩余工作將由合成線程完成。
- 合成線程首先對每個圖層進行分塊 、將其劃分為更小的區(qū)域。它會從線程池中拿取多個線程來完成分塊工作。
- 分塊完成后進入光柵化階段:
- 合成線程會將塊信息交給GPU進程,以極高的速度完成光柵化。
- GPU進程會開啟多個線程來完成光柵化,并且有限處理靠近視口區(qū)域的塊。
- 光柵化的結(jié)果就是一塊一塊的位圖。
- 最后一個階段,就是畫了:
- 合成線程拿到每個層、每個塊的位圖后,生成一個個指引信息。
- 指引會標(biāo)識出每個位圖應(yīng)該畫到屏幕的哪個位置,以及會考慮到旋轉(zhuǎn)、縮放等變形。
- 變形發(fā)生在合成線程,與渲染主線程無關(guān),這就是transform效率高的本質(zhì)原因。
- 合成線程會把指引信息交給GPU進程,由GPU進程產(chǎn)生系統(tǒng)調(diào)用,提交給GPU硬件,完成最終屏幕的生成。
二、什么是reflow(回流)?
reflow的本質(zhì)就是重新計算layout樹。當(dāng)進行了會影響布局樹的操作后,需要重新計算布局樹,會引發(fā)layout。
為了避免連續(xù)的多次操作導(dǎo)致布局樹反復(fù)計算,瀏覽器會合并這些操作,當(dāng)JS代碼全部完成后再進行統(tǒng)一計算。所以,改動屬性造成的reflow是異步完成的。
也同樣因為如此,當(dāng)JS獲取到布局屬性時,就可能造成無法獲取到最新的布局消息。
瀏覽器在反復(fù)權(quán)衡下,最終決定獲取屬性立即reflow。
三、什么時repaint(重繪)?
repaint的本質(zhì)就是重新根據(jù)分層信息計算了繪制指令。當(dāng)改動了可見樣式后就需要重新計算會引發(fā)repaint。
由于元素的布局信息也屬于可見樣式,所以reflow一定會引起repaint。
四、為什么transform的效率高?
因為transform既不會影響布局也不會影響繪制指令,它影響的只是渲染流程的最后一個“畫”階段,由于“畫”階段在合成線程中,所以transform的變化幾乎不會影響渲染主線程。反之,渲染主線程無論如何忙碌,也不會影響transform的變化。