摘要:例如對(duì)于復(fù)雜動(dòng)畫效果,由于會(huì)經(jīng)常的引起回流重繪,因此,我們可以使用絕對(duì)定位,讓它脫離文檔流,成為一個(gè)多帶帶的圖層。
瀏覽器的渲染過(guò)程
從上面這個(gè)圖上,我們可以看到,瀏覽器渲染過(guò)程如下
解析HTML生成DOM樹(shù),解析CSS生成CSSOM樹(shù)
將DOM樹(shù)和CSSOM樹(shù)結(jié)合生成渲染樹(shù)renderTree
Layout(回流): 根據(jù)生成的渲染樹(shù),進(jìn)行回流(Layout),得到節(jié)點(diǎn)的幾何信息(位置,大小)
Painting(重繪): 根據(jù)渲染樹(shù)以及回流得到的幾何信息,得到節(jié)點(diǎn)的絕對(duì)像素
Display:將像素發(fā)送給GPU,展示在頁(yè)面上。
生成渲染樹(shù)(RenderTree)為了構(gòu)建渲染樹(shù),瀏覽器主要完成了以下工作
從DOM樹(shù)的根節(jié)點(diǎn)開(kāi)始遍歷每個(gè)可見(jiàn)節(jié)點(diǎn)。
對(duì)于每個(gè)可見(jiàn)的節(jié)點(diǎn),找到CSSOM樹(shù)中對(duì)應(yīng)的規(guī)則,并應(yīng)用它們。
根據(jù)每個(gè)可見(jiàn)節(jié)點(diǎn)以及其對(duì)應(yīng)的樣式,組合生成渲染樹(shù)。
第一步中,既然說(shuō)到了要遍歷可見(jiàn)的節(jié)點(diǎn),那么我們得先知道,什么節(jié)點(diǎn)是不可見(jiàn)的。不可見(jiàn)的節(jié)點(diǎn)包括:
一些不會(huì)渲染輸出的節(jié)點(diǎn),比如script、meta、link等。
一些通過(guò)css進(jìn)行隱藏的節(jié)點(diǎn)。比如display:none。注意,利用visibility和opacity隱藏的節(jié)點(diǎn),還是會(huì)顯示在渲染樹(shù)上的。只有display:none的節(jié)點(diǎn)才不會(huì)顯示在渲染樹(shù)上。
回流(Layout)前面我們通過(guò)構(gòu)造渲染樹(shù),我們將可見(jiàn)DOM節(jié)點(diǎn)以及它對(duì)應(yīng)的樣式結(jié)合起來(lái),可是我們還需要計(jì)算它們?cè)谠O(shè)備視口(viewport)內(nèi)的確切位置和大小,這個(gè)計(jì)算的階段就是回流。
為了弄清每個(gè)對(duì)象在網(wǎng)站上的確切大小和位置,瀏覽器從渲染樹(shù)的根節(jié)點(diǎn)開(kāi)始遍歷,而在回流這個(gè)階段,我們就需要根據(jù)視口具體的寬度,將其轉(zhuǎn)為實(shí)際的像素值
通過(guò)回流(Layout)階段,我們知道了所有的可見(jiàn)節(jié)點(diǎn)的樣式和具體的幾何信息(位置、大小),那么我們就可以將渲染樹(shù)的每個(gè)節(jié)點(diǎn)都轉(zhuǎn)換為屏幕上的實(shí)際像素,這個(gè)階段就叫做重繪節(jié)點(diǎn)。
何時(shí)發(fā)生回流重繪回流階段是計(jì)算節(jié)點(diǎn)的幾何信息和位置,那么當(dāng)頁(yè)面布局或者幾何信息發(fā)生改變時(shí),就需要回流。
添加或者刪除可見(jiàn)的DOM元素
元素的位置、尺寸發(fā)生變化
頁(yè)面開(kāi)始渲染的時(shí)候(這肯定避免不了)
瀏覽器的視口尺寸大小發(fā)生改變(因?yàn)榛亓魇歉鶕?jù)瀏覽器視口的大小來(lái)計(jì)算元素的位置和尺寸大小)
注意:回流一定會(huì)觸發(fā)重繪,而重繪(非幾何信息的樣式發(fā)生改變)不一定會(huì)回流, reflow回流的成本開(kāi)銷要高于repaint重繪,一個(gè)節(jié)點(diǎn)的回流往往回導(dǎo)致子節(jié)點(diǎn)以及同級(jí)節(jié)點(diǎn)的回流;
根據(jù)改變的范圍和程度,渲染樹(shù)中或大或小的部分需要重新計(jì)算,有些改變會(huì)觸發(fā)整個(gè)頁(yè)面的重排,比如,滾動(dòng)條出現(xiàn)的時(shí)候或者修改了根節(jié)點(diǎn)。
基于回流(Layout)、重繪(Painting)的優(yōu)化方法 避免擾亂現(xiàn)代瀏覽器的優(yōu)化機(jī)制在現(xiàn)代瀏覽器的中,由于每次回流、重繪的時(shí)候,都需要額外的計(jì)算消耗,因此會(huì)通過(guò)隊(duì)列化修改,并批量執(zhí)行來(lái)優(yōu)化這一過(guò)程。瀏覽器會(huì)將修改操作放入隊(duì)列里面,直到過(guò)了一段時(shí)間或者達(dá)到一個(gè)閾值,才清空隊(duì)列。
但是當(dāng)你獲取布局信息時(shí),會(huì)強(qiáng)制刷新隊(duì)列,例如:
offsetTop、offsetLeft、offsetWidth、offsetHeight scrollTop、scrollLeft、scrollWidth、scrollHeight clientTop、clientLeft、clientWidth、clientHeight getComputedStyle() getBoundingClientRect()
上面這些方法,都需要獲取最新的布局信息,所以瀏覽器會(huì)強(qiáng)制刷新隊(duì)列并執(zhí)行回流、重繪,來(lái)獲取最新的信息。
因此我們?cè)谛薷臉邮降臅r(shí)候,應(yīng)該盡量避免使用上面的屬性、方法,如果非要使用,可以先緩存起來(lái)然后一起獲取。
考慮以下代碼
const el = document.getElementById("el") el.style.padding = "xxx" el.style.margin = "xxx" el.style.border = "xxx"
這里元素的幾何信息有三次被修改了,但是現(xiàn)代瀏覽器會(huì)將起緩存起來(lái),但是如果這期間有通過(guò)前面列出來(lái)的屬性、方法訪問(wèn)位置信息的話就會(huì)觸發(fā)三次回流、重繪。所以還是建議通過(guò)cssText或者class的方法一次性修改。
el.style.cssText += "border-left: 1px; border-right: 2px; padding: 5px;"; // 或者 el.className += "xxx";批量修改DOM
當(dāng)我們需要對(duì)DOM進(jìn)行一系列修改的時(shí)候,可以通過(guò)以下幾種方式減少回流重繪次數(shù):
隱藏元素,應(yīng)用修改,重新顯示
function appendDataToElement (appendToElement, data) { let li; for ( let i = 0; i < data.length; i++) { li = document.createElement("li"); li.textContent = "text"; appendToElement.appendChild(li); } } const ul = document.getElementById("list"); ul.style.display = "none"; // 首先脫離文檔流 appendDataToElement(ul, data); ul.style.display = "block"; // 操作完以后再可見(jiàn)
使用文檔片段(document fragment)在當(dāng)前DOM之外構(gòu)建一個(gè)子樹(shù),再把它拷貝回文檔。
const ul = document.getElementById("list"); const fragment = document.createDocumentFragment() appendDataToElement(fragment , data); ul.appendChild(fragment )獨(dú)立圖層
一個(gè)圖層的回流和重繪只會(huì)在該圖層當(dāng)中進(jìn)行,不會(huì)影響其他圖層,所以有必要的時(shí)候,可以將某些元素放到多帶帶的圖層。
例如對(duì)于復(fù)雜動(dòng)畫效果,由于會(huì)經(jīng)常的引起回流重繪,因此,我們可以使用絕對(duì)定位,讓它脫離文檔流, 成為一個(gè)多帶帶的圖層。否則會(huì)引起父元素以及后續(xù)元素頻繁的回流。但是因該盡量少量使用圖層,因?yàn)閳D層的合成是特別消耗性能,一個(gè)頁(yè)面當(dāng)中不能有過(guò)多的圖層, 在使用了圖層之后需要進(jìn)行前后對(duì)比
會(huì)自動(dòng)建立圖層的情況:
3d或者透視變換、過(guò)渡css屬性
使用
flash
多透明度做 css動(dòng)畫
其他優(yōu)化用translate替代top改變: top會(huì)觸發(fā)回流,而前者不會(huì)
用opacity替代visibility: 前者回流重繪都不會(huì)觸發(fā)(前提是它多帶帶在一個(gè)圖層),后者兩個(gè)都會(huì)觸發(fā)
不要使用table布局,table的可能很小的一個(gè)改動(dòng)會(huì)造成回流,很影響性能,應(yīng)該盡量使用 div。
動(dòng)畫實(shí)現(xiàn)的速度選擇:
對(duì)于動(dòng)畫新建圖層
啟用GPU硬件加速: 使用transform:translateZ(0) 、transform:translate3d(0,0,0)來(lái)開(kāi)啟GPU硬件加速
CSS 與 JS 是這樣阻塞 DOM 解析和渲染的通過(guò)與引入外部資源,當(dāng)解析到該標(biāo)簽的時(shí)候,會(huì)進(jìn)行下載。
CSS腳本的加載不會(huì)阻塞 DOM 解析過(guò)程,但是會(huì)阻塞渲染過(guò)程(painting)
JS腳本的加載與執(zhí)行會(huì)阻塞 DOM 解析過(guò)程, 但是不會(huì)阻塞后續(xù)資源的加載
JS腳本的加載中,如果你確定沒(méi)必要阻塞 DOM 解析的話,不妨按需要加上 defer 或者 async 屬性,此時(shí)腳本下載的過(guò)程中是不會(huì)阻塞 DOM 解析的。
瀏覽器遇到 且沒(méi)有 defer 或 async 屬性的標(biāo)簽時(shí),為了為標(biāo)簽內(nèi)部的js提供最新的信息,會(huì)觸發(fā)頁(yè)面的回流、重繪過(guò)程。
如果前面 CSS 資源尚未加載完畢時(shí),瀏覽器會(huì)等待它加載完畢之后再執(zhí)行腳本。即 css 不阻塞 js 的加載,但阻塞它的執(zhí)行。
所以最好放底部(防止阻塞DOM解析)。最好放頭部(為渲染過(guò)程提供樣式)。如果頭部同時(shí)有與的情況下,最好將放在上面(為了防止CSS腳本加載時(shí)間過(guò)長(zhǎng),使js等待時(shí)間也很長(zhǎng))dd
defer和async直接看圖吧,綠色的代表 html 解析,藍(lán)色的代表 javascript 腳本的下載,紅色的代表 javaScript 腳本的執(zhí)行。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/53475.html
摘要:所以由此來(lái)看重繪不一定導(dǎo)致回流,回流一定會(huì)導(dǎo)致重繪前面我們說(shuō)回流和重繪是會(huì)對(duì)進(jìn)行修改,會(huì)消耗性能,所以我們要盡可能減少回流和重繪的次數(shù)。瀏覽器自己也清楚,如果每次操作都即時(shí)地反饋一次回流或重繪,那么性能上來(lái)說(shuō)是扛不住的。 回流(Reflow)重繪(Repaint) 什么時(shí)候會(huì)觸發(fā)回流或重繪呢? 當(dāng)我們對(duì)dom 進(jìn)行修改當(dāng)時(shí)候會(huì)引發(fā)它外觀(樣式)上的改變時(shí),就會(huì)觸發(fā)回流或重繪。這個(gè)過(guò)程本...
摘要:何時(shí)發(fā)生有大量的用戶行為以及潛在的改變會(huì)觸發(fā)回流。這樣就會(huì)讓多次的回流重繪變成一次回流重繪。因?yàn)樯系牟僮鞑粫?huì)引發(fā)回流和重繪。參考文章回流與重繪性能讓變慢參考文章瀏覽器的重繪與重排 推薦了解的知識(shí):基本的HTML,基本的JavaScript,以及一些css工作原理方面的知識(shí) 瀏覽器的渲染原理 css的加載和解析不會(huì)阻塞html文檔的解析 css的解析會(huì)阻塞js的執(zhí)行,必須等到CSSOM...
摘要:對(duì)于復(fù)雜動(dòng)畫效果使用絕對(duì)定位讓其脫離文檔流對(duì)于復(fù)雜動(dòng)畫效果,由于會(huì)經(jīng)常的引起回流重繪,因此,我們可以使用絕對(duì)定位,讓它脫離文檔流。硬件加速加速比起考慮如何減少回流重繪,我們更期望的是,根本不要回流重繪。 回流和重繪可以說(shuō)是每一個(gè)web開(kāi)發(fā)者都經(jīng)常聽(tīng)到的兩個(gè)詞語(yǔ),我也不例外,可是我之前一直不是很清楚這兩步具體做了什么事情。最近由于部門內(nèi)部要做分享,所以對(duì)其進(jìn)行了一些研究,看了一些博客和書...
摘要:否則會(huì)引起父元素以及后續(xù)元素頻繁的回流。硬件加速加速硬件加速加速比起考慮如何減少回流重繪,我們更期望的是,根本不要回流重繪。這個(gè)時(shí)候,硬件加速就閃亮登場(chǎng)啦劃重點(diǎn)使用硬件加速,可以讓這些動(dòng)畫不會(huì)引起回流重繪。回流和重繪可以說(shuō)是每一個(gè)web開(kāi)發(fā)者都經(jīng)常聽(tīng)到的兩個(gè)詞語(yǔ),我也不例外,可是一直不是很清楚這兩步具體做了什么事情。最近由于部門內(nèi)部要做分享,所以對(duì)其進(jìn)行了一些研究,看了一些博客和書籍,整理了...
摘要:硬件加速加速比起考慮如何減少回流重繪,我們更期望的是,根本不要回流重繪。這個(gè)時(shí)候,硬件加速就閃亮登場(chǎng)啦劃重點(diǎn)使用硬件加速,可以讓這些動(dòng)畫不會(huì)引起回流重繪。 本文由云+社區(qū)發(fā)表 回流和重繪可以說(shuō)是每一個(gè)web開(kāi)發(fā)者都經(jīng)常聽(tīng)到的兩個(gè)詞語(yǔ),可是可能有很多人不是很清楚這兩步具體做了什么事情。最近有空對(duì)其進(jìn)行了一些研究,看了一些博客和書籍,整理了一些內(nèi)容并且結(jié)合一些例子,寫了這篇文章,希望可以幫...
閱讀 2772·2021-11-02 14:42
閱讀 3163·2021-10-08 10:04
閱讀 1184·2019-08-30 15:55
閱讀 1025·2019-08-30 15:54
閱讀 2311·2019-08-30 15:43
閱讀 1680·2019-08-29 15:18
閱讀 863·2019-08-29 11:11
閱讀 2362·2019-08-26 13:52