摘要:之后,如果渲染樹發(fā)生了變動,那么可能會觸發(fā)回流或重繪中的一個或二者。在書寫時要避免不必要的層級,書寫時避免嵌套過深規(guī)則過于復雜,尤其是后代選擇器,匹配選擇器也會耗費更多的。
剛入行前端的時候是不是經(jīng)常看到有文章說盡量不要用CSS通配符*,CSS選擇器層疊最好不要超過三層,HTML少使用table,結構也要盡量簡單一些...這一切說的不無道理,過多的使用確實會造成瀏覽器渲染的性能降低,當你認識了reflow和repaint之后,你會發(fā)現(xiàn)這些還真不能用太多。
一、瀏覽器渲染過程不同的瀏覽器渲染過程實際上并不相同(由渲染引擎決定),但是依舊存在一致的部分,大致過程如下圖:
解析HTML以構建DOM樹:渲染引擎解析HTML文檔,轉換樹中的HTML標簽或JS生成的標簽生成DOM節(jié)點
解析CSS以構建樣式結構體:渲染引擎解析CSS(包括外部CSS文件、樣式元素以及JS生成的樣式)成樣式結構體,根據(jù)CSS選擇器計算出節(jié)點的樣式
構建渲染樹:從根節(jié)點遞歸調用,計算每一個元素的大小、位置以及每個節(jié)點所應該出現(xiàn)在屏幕上的精確坐標
繪制渲染樹:渲染引擎遍歷渲染樹將其繪制出來
二、什么是 reflow & repaint其實在上面瀏覽器渲染過程中的第三步和第四步分別就是回流(reflow)和重繪(repaint)。當?shù)谝淮未蜷_一個頁面時,至少會有一次回流和重繪。之后,如果渲染樹發(fā)生了變動,那么可能會觸發(fā)回流或重繪中的一個或二者。
回流:如果渲染樹的節(jié)點發(fā)生了結構性變化,例如寬高、位置、隱藏上有變化時,那么就會觸發(fā)一次回流
重繪:如果渲染樹的節(jié)點發(fā)生了非結構性變化,例如背景色、顏色、字體上有變化時,那么就會觸發(fā)一次重繪
回流必將引起重繪,而重繪不一定會引起回流。回流的成本比重繪的成本要高得多,因為一個節(jié)點的回流很有可能導致子結點,父節(jié)點回流。
三、觸發(fā) reflow & repaint頁面初始化渲染
DOM元素的添加、修改、刪除
移動DOM或著DOM發(fā)生了動畫
resize瀏覽器窗口、滾動頁面
修改DOM元素的字體顏色
激活CSS偽類
某個樣式的添加、修改、刪除
display: none會觸發(fā)reflow,visibility: hidden只會觸發(fā)repaint,因為沒有發(fā)生位置變化
讀取元素的某些屬性(沒想到吧...)
現(xiàn)代瀏覽器會對回流做優(yōu)化,它會等到足夠數(shù)量的變化發(fā)生,再做一次批處理回流。但是當獲取某些屬性時,瀏覽器為了獲得正確的值也會提前觸發(fā)回流,這樣就使得瀏覽器的優(yōu)化失效了,這些屬性包括offsetLeft、offsetTop、offsetWidth、offsetHeight、 scrollTop/Left/Width/Height、clientTop/Left/Width/Height、調用了getComputedStyle()或者IE的currentStyle
四、減少 reflow & repaint回流和重繪是不可避免的,我們只能說將它們對性能的影響減到最小,既然我們知道什么情況會觸發(fā)它們,那就從這些方面入手:
讓需要改變的元素進行“離線處理”,處理完后一起更新
使用DocumentFragment進行緩存操作,觸發(fā)一次回流和重繪
使用display: none,觸發(fā)兩次回流和重繪(由于display: none的元素不在渲染樹中,對隱藏的元素操作不會引發(fā)其他元素的回流,可以先隱藏它,操作完成后再顯示。這樣只在隱藏和顯示時觸發(fā)2次回流)
將需要多次回流的元素的position屬性設為absolute或fixed(設為float沒有完全脫離文檔流,這個很微妙),這樣元素就脫離了文檔流,它的變化不會影響到其他元素的布局,不會導致一個完整回流
不要把DOM節(jié)點的屬性值放在一個循環(huán)里作為循環(huán)的變量,這會導致大量地讀寫這個節(jié)點的屬性
不要一條一條地修改樣式,將多次改變樣式屬性的操作合并成一次(一般人也不會這樣做)
不要用table布局,table中某個元素一旦觸發(fā)回流就會導致table里所有的其它元素回流。在適合用table的場合,可以設置table-layout為auto或fixed,這樣可以讓table一行一行的渲染,這種做法也是為了限制回流的影響范圍(一般我們可以通過ul li的布局替代之)
避免使用CSS的JavaScript表達式(這種規(guī)則已過時)
總之,在以后的開發(fā)中我們要盡量避免大量、頻繁的操作DOM元素,因為DOM操作的代價實在是太昂貴了(這也是Virtual DOM應運而生的原因)。在書寫HTML時要避免不必要的層級,書寫CSS時避免嵌套過深、規(guī)則過于復雜,尤其是后代選擇器,匹配選擇器也會耗費更多的CPU。
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/112647.html
摘要:寫在金三銀四之際。一個節(jié)點觸發(fā)了,瀏覽器會檢查中其他所有節(jié)點的顯示方式一個節(jié)點觸發(fā)了會導致它的祖先節(jié)點,后代節(jié)點以及在它之后的節(jié)點全部。對性能的影響大于。解決方式控制我們無力去改變,對性能損害的程度,我們能做的只有減少它們發(fā)生的次數(shù)。 寫在金三銀四之際。 因為種種原因想要謀求新的發(fā)展,不得已翻起了塵封已久的高程書;寫起了各種經(jīng)典CSS布局;回顧起記憶略顯模糊的幾個項目。感慨著太多太多...
摘要:渲染層合并對頁面中元素的繪制是在多個層上進行的。擁有兩套不同的渲染路徑硬件加速路徑和舊軟件路徑中有不同類型的層負責子樹和負責的子樹,只有是作為紋理上傳給的。整個圖在中其實有幾種不同的層類型渲染層,這是負責對應子樹圖形層,這是負責對應子樹。 梳理瀏覽器渲染流程 首先簡單了解一下瀏覽器請求、加載、渲染一個頁面的大致過程: DNS 查詢 TCP 連接 HTTP 請求即響應 服務器響應 客戶...
摘要:渲染層合并對頁面中元素的繪制是在多個層上進行的。擁有兩套不同的渲染路徑硬件加速路徑和舊軟件路徑中有不同類型的層負責子樹和負責的子樹,只有是作為紋理上傳給的。整個圖在中其實有幾種不同的層類型渲染層,這是負責對應子樹圖形層,這是負責對應子樹。 梳理瀏覽器渲染流程 首先簡單了解一下瀏覽器請求、加載、渲染一個頁面的大致過程: DNS 查詢 TCP 連接 HTTP 請求即響應 服務器響應 客戶...
摘要:渲染層合并對頁面中元素的繪制是在多個層上進行的。擁有兩套不同的渲染路徑硬件加速路徑和舊軟件路徑中有不同類型的層負責子樹和負責的子樹,只有是作為紋理上傳給的。整個圖在中其實有幾種不同的層類型渲染層,這是負責對應子樹圖形層,這是負責對應子樹。 梳理瀏覽器渲染流程 首先簡單了解一下瀏覽器請求、加載、渲染一個頁面的大致過程: DNS 查詢 TCP 連接 HTTP 請求即響應 服務器響應 客戶...
閱讀 1252·2023-04-25 18:57
閱讀 2137·2023-04-25 16:28
閱讀 3935·2021-11-24 09:39
閱讀 3636·2021-11-16 11:45
閱讀 1824·2021-10-13 09:40
閱讀 1265·2019-08-30 15:52
閱讀 1721·2019-08-30 10:57
閱讀 663·2019-08-29 16:55