成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

根據(jù)瀏覽器渲染界面原理理解渲染阻塞、瀏覽器的重繪(repaints)與回流(reflows)

phodal / 3561人閱讀

摘要:渲染阻塞在瀏覽器進(jìn)行加載時(shí),其實(shí)是并行加載所有資源。則就叫稱為重繪。在回流的時(shí)候,瀏覽器會使渲染樹中受到影響的部分失效,并重新構(gòu)造這部分渲染樹,完成回流后,瀏覽器會重新繪制受影響的部分到屏幕中,該過程成為重繪。

前面有講到當(dāng)用戶在瀏覽器輸入url之后,經(jīng)過一系列的過程,會最終向服務(wù)器請求到文檔數(shù)據(jù),文檔數(shù)據(jù)請求到之后,瀏覽器會將這些數(shù)據(jù)傳給瀏覽器渲染引擎,渲染引擎開始正式工作了。

構(gòu)建dom樹,解析css

首先瀏覽器接收到html文檔,就會把HTML在內(nèi)存中轉(zhuǎn)換成DOM樹,HTML中的每個(gè)tag都是DOM樹中的1個(gè)節(jié)點(diǎn),根節(jié)點(diǎn)就是我們常用的document對象。DOM樹里包含了所有HTML標(biāo)簽,包括display:none隱藏,還有用JS動態(tài)添加的元素等。在轉(zhuǎn)換的過程中如果發(fā)現(xiàn)某個(gè)節(jié)點(diǎn)(node)上引用了CSS或者 image,就會再次向服務(wù)器請求css或image,然后繼續(xù)執(zhí)行構(gòu)建dom樹的轉(zhuǎn)換,而不需要等待請求的返回,當(dāng)請求的css文件返回后,就會開始解析css style,瀏覽器把所有樣式(用戶定義的CSS和用戶代理)解析成樣式結(jié)構(gòu)體,在解析的過程中會去掉瀏覽器不能識別的樣式,比如IE會去掉-moz開頭的樣式,而FF會去掉_開頭的樣式。

構(gòu)建render Tree及繪制

DOM Tree 和樣式結(jié)構(gòu)體組合后構(gòu)建render tree,也就是渲染樹。渲染樹和dom樹有很大的區(qū)別,render tree中每個(gè)NODE都有自己的style,而且 render tree不包含隱藏的節(jié)點(diǎn) (比如display:none的節(jié)點(diǎn),還有head節(jié)點(diǎn)),因?yàn)檫@些節(jié)點(diǎn)不會用于呈現(xiàn),而且不會影響呈現(xiàn)的,所以就不會包含到 render tree中。注意 visibility:hidden隱藏的元素還是會包含到 render tree中的,因?yàn)関isibility:hidden 會影響布局(layout),會占有空間。根據(jù)CSS2的標(biāo)準(zhǔn),render tree中的每個(gè)節(jié)點(diǎn)都稱為Box (Box dimensions),理解頁面元素為一個(gè)具有填充、邊距、邊框和位置的盒子。一旦render tree構(gòu)建完畢后,瀏覽器就可以根據(jù)render tree來繪制頁面了。

注意:由于瀏覽器的流布局,對渲染樹的計(jì)算通常只需要遍歷一次就可以完成。但 table及其內(nèi)部元素除外,它可能需要多次計(jì)算才能確定好其在渲染樹中節(jié)點(diǎn)的屬性,通常要花3倍于同等元素的時(shí)間。這也是為什么我們要避免使用 table做布局的一個(gè)原因。

渲染阻塞

在瀏覽器進(jìn)行加載時(shí),其實(shí)是并行加載所有資源。對于css和圖片等資源,瀏覽器加載是異步的,并不會影響到后續(xù)的加載、html解析和后續(xù)渲染。

css阻塞渲染

由上面過程可以看到,頁面布局是在渲染樹構(gòu)建好之后發(fā)生的,而渲染樹依賴css樣式結(jié)構(gòu)體,所以CSS 被視為阻塞渲染的資源但不阻塞html的解析,不會阻塞dom樹的構(gòu)建),這意味著瀏覽器將不會渲染任何已處理的內(nèi)容,直至 CSSOM 構(gòu)建完畢。

因?yàn)閏ss會阻塞渲染,所以我們應(yīng)該盡早的盡快地下載到客戶端,以便縮短首次渲染的時(shí)間。平時(shí)在開發(fā)的時(shí)候,應(yīng)注意以下幾點(diǎn):

將CSS放在head,不管內(nèi)聯(lián)還是外聯(lián)都盡早開始下載或者構(gòu)建CSSOM(前提是這個(gè)CSS是首屏必須的)

避免使用CSS import,CSS中可以用import將另一個(gè)樣式表引入,不過這樣會在構(gòu)建CSSOM時(shí)會增加一次網(wǎng)絡(luò)來回時(shí)間。

適度內(nèi)聯(lián)CSS,衡量其他因素,如外聯(lián),看網(wǎng)絡(luò)來回影響多大,考慮css文件的大小

全面考慮渲染情況,網(wǎng)速差、文件下載失敗等,防止白屏?xí)r間太長

同時(shí),還有以下優(yōu)化點(diǎn):

一、媒體查詢

通過使用媒體查詢,我們可以根據(jù)特定的需求(比如顯示或打?。?,也可以根據(jù)動態(tài)情況(比如屏幕方向變化、尺寸調(diào)整事件等)定制外觀,



看上面的代碼,
第一行,這樣的普通聲明,會阻塞渲染
第二行,這個(gè)聲明,只在打印網(wǎng)頁時(shí)應(yīng)用,因此網(wǎng)頁在瀏覽器中加載時(shí),不會阻塞渲染。
第三行,提供了由瀏覽器執(zhí)行的“媒體查詢”,只有符合條件時(shí),樣式表會生效,瀏覽器才會阻塞渲染,直至樣式表下載并處理完畢。

二、preload

preload是resoure hint規(guī)范中定義的一個(gè)功能,顧名思義預(yù)加載,將rel改為preload后,相當(dāng)于加了一個(gè)標(biāo)志位,瀏覽器解析的時(shí)候會提前建立連接或加載資源,做到盡早并行下載,然后在onload事件響應(yīng)后將link的rel屬性改為stylesheet即可進(jìn)行解析。

IE chrome firefox三者的差異

IE 只要看到HTML 標(biāo)簽就會進(jìn)行繪制

chrome 不管css放在前面還是后面,都要等到CSSOM構(gòu)建形成后才會繪制到頁面上

firefox 放在head則會阻塞繪制,放在body末尾會先繪制前面的標(biāo)簽

三、動態(tài)添加link

var style = document.createElement("link");
style.rel = "stylesheet";
style.href = "index.css";
document.head.appendChild(style);

js動態(tài)添加DOM元素link,不會阻塞渲染。
loadCSS.js,CSS preload polyfill第三方庫,原理同上

四、代碼簡練

js阻塞

js可能會操作html,css,由于瀏覽器不了解腳本計(jì)劃在頁面上執(zhí)行什么操作,它會作最壞的假設(shè)并阻止解析器,也就是之前講過瀏覽器的GUI線程與js引擎線程是互斥的。所以,js會阻塞渲染

瀏覽器對于js腳本文件的加載,則會導(dǎo)致html解析和渲染停止,直至js腳本加載并執(zhí)行完畢才繼續(xù),但是對于后續(xù)的非js資源加載并不會停止,瀏覽器會對后續(xù)資源進(jìn)行預(yù)加載。而資源加載是屬于另外多帶帶的線程,所以js加載并不會影響其他非js資源的加載,是瀏覽器的機(jī)制。

總的來說就是以下幾點(diǎn):

js腳本在文檔中的位置很重要,因?yàn)槠涓鷋tml和css有很強(qiáng)的依賴關(guān)系

在HTML解析器解析到script標(biāo)簽后,會停止DOM構(gòu)建

javascript可以操作DOM和CSSOM,但進(jìn)行這些行為時(shí)要確保相應(yīng)DOM和CSSOM已經(jīng)存在,

JavaScript 執(zhí)行將暫停,直至 CSSOM 就緒

當(dāng)CSS后面跟著嵌入的JS的時(shí)候,該CSS就會出現(xiàn)阻塞后面資源下載的情況,因?yàn)闉g覽器會維持html中css和js的順序,樣式表必須在嵌入的JS執(zhí)行前先加載、解析完。而嵌入的JS會阻塞后面的資源加載,所以就會出現(xiàn)CSS阻塞下載的情況。

使用chrome瀏覽器的performance工具查看瀏覽器的渲染過程:

例如下面這段代碼,看瀏覽器是如何一步步將界面繪制出來




    
    
    
    瀏覽器渲染
    



    

fgdgg

fgdgg

fgdgg

fgdgg

fgdgg

通過瀏覽器的工具上的可以很清楚的看到界面的渲染過程,也可以很清楚的看到請求加載資源的時(shí)候,不會對html解析造成影響,但如果資源加載過慢,會導(dǎo)致渲染阻塞,通過此圖可以很好的理解瀏覽器的渲染機(jī)制

如果我把js放在css之后,如下代碼:




    
    
    
    瀏覽器渲染
    
    



    

fgdgg

fgdgg

fgdgg

fgdgg

fgdgg

再次查看瀏覽器的渲染過程:

圖中可以明顯的看出,首先瀏覽器開始解析html,然后再解析的過程中遇到css,開始加載css資源,遇到j(luò)s開始加載js資源,當(dāng)css加載完成后,開始解析css,js加載完成后,則開始解析js,此時(shí)解析html生成dom樹會停止,直到j(luò)s解析完成之后,才再次開始解析html,重新計(jì)算樣式,布局,生成渲染樹,最終才是界面繪制,所以在開發(fā)的時(shí)候不要將js文件寫在頭部,這樣會影響界面的繪制,導(dǎo)致界面出現(xiàn)空白

瀏覽器的重繪(repaints)與回流(reflows)

重繪
當(dāng)render tree中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀,風(fēng)格,而不會影響布局的,比如background-color。則就叫稱為重繪。

回流
當(dāng)render tree中的一部分(或全部)因?yàn)樵氐囊?guī)模尺寸,布局,隱藏等改變而需要重新構(gòu)建。這就稱為回流(reflow)。
每個(gè)頁面至少需要一次回流,就是在頁面第一次加載的時(shí)候。在回流的時(shí)候,瀏覽器會使渲染樹中受到影響的部分失效,并重新構(gòu)造這部分渲染樹,完成回流后,瀏覽器會重新繪制受影響的部分到屏幕中,該過程成為重繪。

回流必然會造成重繪,重繪不會造成回流。

回流何時(shí)發(fā)生:

當(dāng)頁面布局和幾何屬性改變時(shí)就需要回流。下述情況會發(fā)生瀏覽器回流:

1、添加或者刪除可見的DOM元素;

2、元素位置改變;

3、元素尺寸改變——邊距、填充、邊框、寬度和高度

4、內(nèi)容改變——比如文本改變或者圖片大小改變而引起的計(jì)算值寬度和高度改變;

5、頁面渲染初始化;

6、瀏覽器窗口尺寸改變——resize事件發(fā)生時(shí);

回流比重繪的代價(jià)要更高,回流的花銷跟render tree有多少節(jié)點(diǎn)需要重新構(gòu)建有關(guān)系,假設(shè)你直接操作body,比如在body最前面插入1個(gè)元素,會導(dǎo)致整個(gè)render tree回流,這樣代價(jià)當(dāng)然會比較高,但如果是指body后面插入1個(gè)元素,則不會影響前面元素的回流。

如果每句JS操作都去回流重繪的話,瀏覽器可能就會受不了。所以很多瀏覽器都會優(yōu)化這些操作,瀏覽器會維護(hù)1個(gè)隊(duì)列,把所有會引起回流、重繪的操作放入這個(gè)隊(duì)列,等隊(duì)列中的操作到了一定的數(shù)量或者到了一定的時(shí)間間隔,瀏覽器就會flush隊(duì)列,進(jìn)行一個(gè)批處理。這樣就會讓多次的回流、重繪變成一次回流重繪。

雖然有了瀏覽器的優(yōu)化,但有時(shí)候我們寫的一些代碼可能會強(qiáng)制瀏覽器提前flush隊(duì)列,這樣瀏覽器的優(yōu)化可能就起不到作用了。當(dāng)你請求向?yàn)g覽器請求一些 style信息的時(shí)候,就會讓瀏覽器flush隊(duì)列,比如:

offsetTop, offsetLeft, offsetWidth, offsetHeight

scrollTop/Left/Width/Height

clientTop/Left/Width/Height

width,height

請求了getComputedStyle(), 或者 IE的 currentStyle

當(dāng)請求上面的一些屬性的時(shí)候,瀏覽器為了給你最精確的值,需要flush隊(duì)列,因?yàn)殛?duì)列中可能會有影響到這些值的操作。即使你獲取元素的布局和樣式信息跟最近發(fā)生或改變的布局信息無關(guān),瀏覽器都會強(qiáng)行刷新渲染隊(duì)列。

盡量減少回流和重繪

因?yàn)榛亓鞯拈_銷很大,所以我們在寫代碼的時(shí)候,有很多需要注意的地方:

不要一個(gè)一個(gè)改變元素的樣式屬性,最好直接改變className,但className是預(yù)先定義好的樣式,不是動態(tài)的,如果你要動態(tài)改變一些樣式,則使用cssText來改變,如下:

// 不好的寫法  
var left = 1;  
var top = 1;  
el.style.left = left + "px";  
el.style.top  = top  + "px";  
 
// 比較好的寫法   
el.className += " className1";  
 
// 比較好的寫法   
el.style.cssText += "; left: " + left + "px; top: " + top + "px;";

讓要操作的元素進(jìn)行"離線處理",處理完后一起更新,這里所謂的"離線處理"即讓元素不存在于render tree中

a、使用documentFragment或div等元素進(jìn)行緩存操作,這個(gè)主要用于添加元素的時(shí)候,大家應(yīng)該都用過,就是先把所有要添加到元素添加到1個(gè)div(這個(gè)div也是新加的),最后才把這個(gè)div append到body中。
b、先display:none 隱藏元素,然后對該元素進(jìn)行所有的操作,最后再顯示該元素。因?qū)isplay:none的元素進(jìn)行操作不會引起回流、重繪。所以只要操作只會有2次回流。

不要經(jīng)常訪問會引起瀏覽器flush隊(duì)列的屬性,如果你確實(shí)要訪問,就先讀取到變量中進(jìn)行緩存,以后用的時(shí)候直接讀取變量就可以了,見下面代碼:

// 別這樣寫 
for(循環(huán)) {  
    elel.style.left = el.offsetLeft + 5 + "px";  
    elel.style.top  = el.offsetTop  + 5 + "px";  
}  
 
// 這樣寫好點(diǎn)  
var left = el.offsetLeft,top  = el.offsetTop,s = el.style;  
for(循環(huán)) {  
    left += 10;  
    top  += 10;  
    s.left = left + "px";  
    s.top  = top  + "px";  
}

考慮你的操作會影響到render
tree中的多少節(jié)點(diǎn)以及影響的方式,影響越多,花費(fèi)肯定就越多。比如現(xiàn)在很多人使用jquery的animate方法移動元素來展示一些動畫效果,想想下面2種移動的方法:

// block1是position:absolute 定位的元素,它移動會影響到它父元素下的所有子元素。  
// 因?yàn)樵谒苿舆^程中,所有子元素需要判斷block1的z-index是否在自己的上面,  
// 如果是在自己的上面,則需要重繪,這里不會引起回流  
$("#block1").animate({left:50});  
// block2是相對定位的元素,這個(gè)影響的元素與block1一樣,但是因?yàn)閎lock2非絕對定位  
// 而且改變的是marginLeft屬性,所以這里每次改變不但會影響重繪,  
// 還會引起父元素及其下元素的回流  
$("#block2").animate({marginLeft:50});

參考文章:
https://www.cnblogs.com/kevin...
https://blog.csdn.net/allenli...
https://www.css88.com/archive...

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/99326.html

相關(guān)文章

  • 根據(jù)覽器渲染界面原理理解渲染阻塞、覽器重繪repaints回流reflows

    摘要:渲染阻塞在瀏覽器進(jìn)行加載時(shí),其實(shí)是并行加載所有資源。則就叫稱為重繪。在回流的時(shí)候,瀏覽器會使渲染樹中受到影響的部分失效,并重新構(gòu)造這部分渲染樹,完成回流后,瀏覽器會重新繪制受影響的部分到屏幕中,該過程成為重繪。 前面有講到當(dāng)用戶在瀏覽器輸入url之后,經(jīng)過一系列的過程,會最終向服務(wù)器請求到文檔數(shù)據(jù),文檔數(shù)據(jù)請求到之后,瀏覽器會將這些數(shù)據(jù)傳給瀏覽器渲染引擎,渲染引擎開始正式工作了。 構(gòu)建...

    daryl 評論0 收藏0
  • 根據(jù)覽器渲染界面原理理解渲染阻塞、覽器重繪repaints回流reflows

    摘要:渲染阻塞在瀏覽器進(jìn)行加載時(shí),其實(shí)是并行加載所有資源。則就叫稱為重繪。在回流的時(shí)候,瀏覽器會使渲染樹中受到影響的部分失效,并重新構(gòu)造這部分渲染樹,完成回流后,瀏覽器會重新繪制受影響的部分到屏幕中,該過程成為重繪。 前面有講到當(dāng)用戶在瀏覽器輸入url之后,經(jīng)過一系列的過程,會最終向服務(wù)器請求到文檔數(shù)據(jù),文檔數(shù)據(jù)請求到之后,瀏覽器會將這些數(shù)據(jù)傳給瀏覽器渲染引擎,渲染引擎開始正式工作了。 構(gòu)建...

    ranwu 評論0 收藏0
  • 覽器回流重繪及其優(yōu)化方式

    摘要:何時(shí)發(fā)生有大量的用戶行為以及潛在的改變會觸發(fā)回流。這樣就會讓多次的回流重繪變成一次回流重繪。因?yàn)樯系牟僮鞑粫l(fā)回流和重繪。參考文章回流與重繪性能讓變慢參考文章瀏覽器的重繪與重排 推薦了解的知識:基本的HTML,基本的JavaScript,以及一些css工作原理方面的知識 瀏覽器的渲染原理 css的加載和解析不會阻塞html文檔的解析 css的解析會阻塞js的執(zhí)行,必須等到CSSOM...

    hearaway 評論0 收藏0
  • 覽器渲染頁面過程頁面優(yōu)化

    摘要:由一道面試題引發(fā)的思考從用戶輸入瀏覽器輸入到頁面最后呈現(xiàn)有哪些過程一道很常規(guī)的題目,考的是基本網(wǎng)絡(luò)原理,和瀏覽器加載,過程。所以抽出時(shí)間研究下瀏覽器渲染頁面的過程。 由一道面試題引發(fā)的思考: 從用戶輸入瀏覽器輸入url到頁面最后呈現(xiàn) 有哪些過程?一道很常規(guī)的題目,考的是基本網(wǎng)絡(luò)原理,和瀏覽器加載css,js過程。 答案大致如下: 用戶輸入U(xiǎn)RL地址 瀏覽器解析URL解析出主機(jī)名 瀏覽...

    djfml 評論0 收藏0
  • 淺談覽器多進(jìn)程JS線程

    摘要:引言一直對瀏覽器的進(jìn)程線程的運(yùn)行一無所知,經(jīng)過一次的刷刷刷相關(guān)的博客之后,對其有了初步的了解,是時(shí)候該總結(jié)一波了。瀏覽器內(nèi)的進(jìn)程知道了進(jìn)程與線程之間的關(guān)系之后,下面是瀏覽器與進(jìn)程的關(guān)系了。 引言 一直對瀏覽器的進(jìn)程、線程的運(yùn)行一無所知,經(jīng)過一次的刷刷刷相關(guān)的博客之后,對其有了初步的了解,是時(shí)候該總結(jié)一波了。 進(jìn)程、線程之間的關(guān)系 一個(gè)進(jìn)程有一個(gè)或多個(gè)線程,線程之間共同完成進(jìn)程分配下來的...

    Juven 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<