日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > HTML >内容正文

HTML

dev 中 gridcontrol1 滚动条重绘_浏览器的重绘和回流(Repaint amp; Reflow)

發(fā)布時(shí)間:2025/3/8 HTML 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 dev 中 gridcontrol1 滚动条重绘_浏览器的重绘和回流(Repaint amp; Reflow) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

參考文獻(xiàn):

https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction?hl=zh-cn?developers.google.com你真的了解回流和重繪嗎 · Issue #4 · chenjigeng/blog?github.com

前言:

重繪:由于節(jié)點(diǎn)的幾何屬性發(fā)生改變或者由于樣式發(fā)生改變而不會(huì)影響布局的,稱為重繪,例如outline,visibility,color、background-color等。

回流:是布局或者幾何屬性需要改變就稱為回流。回流是影響瀏覽器性能的關(guān)鍵因素,因?yàn)槠渥兓婕暗讲糠猪?yè)面(或是整個(gè)頁(yè)面)的布局更新。一個(gè)元素的回流可能會(huì)導(dǎo)致了其所有子元素以及DOM中緊隨其后的節(jié)點(diǎn)、祖先節(jié)點(diǎn)元素的隨后的回流。

測(cè)試:

分別使用left跟translate實(shí)現(xiàn)位移效果,查看重繪&回流對(duì)瀏覽器性能及視覺(jué)效果的影響。

1.left效果:

left效果

2.translate效果:

translate效果

可以看到left一直在重繪&回流,但是translate就不一樣啦,這是因?yàn)镃SS3做了很多優(yōu)化。由此可見(jiàn)重繪&回流帶來(lái)的性能影響及糟糕的用戶體驗(yàn)。

瀏覽器的渲染過(guò)程:

本文先從瀏覽器的渲染過(guò)程來(lái)從頭到尾的講解一下回流重繪,如果大家想直接看如何減少回流和重繪,可以跳到后面。(這個(gè)渲染過(guò)程來(lái)自MDN)

從上面這個(gè)圖上,我們可以看到,瀏覽器渲染過(guò)程如下:

  • 解析HTML,生成DOM樹(shù),解析CSS,生成CSSOM樹(shù)
  • 將DOM樹(shù)和CSSOM樹(shù)結(jié)合,生成渲染樹(shù)(Render Tree)
  • Layout(回流):根據(jù)生成的渲染樹(shù),進(jìn)行回流(Layout),得到節(jié)點(diǎn)的幾何信息(位置,大小)
  • Painting(重繪):根據(jù)渲染樹(shù)以及回流得到的幾何信息,得到節(jié)點(diǎn)的絕對(duì)像素
  • Display:將像素發(fā)送給GPU,展示在頁(yè)面上。(這一步其實(shí)還有很多內(nèi)容,比如會(huì)在GPU將多個(gè)合成層合并為同一個(gè)層,并展示在頁(yè)面中。而css3硬件加速的原理則是新建合成層,這里我們不展開(kāi),之后有機(jī)會(huì)會(huì)寫一篇博客)
  • 渲染過(guò)程看起來(lái)很簡(jiǎn)單,讓我們來(lái)具體了解下每一步具體做了什么。

    生成渲染樹(shù):

    為了構(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ù)上。

    注意:渲染樹(shù)只包含可見(jiàn)的節(jié)點(diǎn)

    回流:

    前面我們通過(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è)實(shí)例來(lái)表示:

    <!DOCTYPE html> <html><head><meta name="viewport" content="width=device-width,initial-scale=1"><title>Critial Path: Hello world!</title></head><body><div style="width: 50%"><div style="width: 50%">Hello world!</div></div></body> </html>

    我們可以看到,第一個(gè)div將節(jié)點(diǎn)的顯示尺寸設(shè)置為視口寬度的50%,第二個(gè)div將其尺寸設(shè)置為父節(jié)點(diǎn)的50%。而在回流這個(gè)階段,我們就需要根據(jù)視口具體的寬度,將其轉(zhuǎn)為實(shí)際的像素值。(如下圖)

    重繪

    最終,我們通過(guò)構(gòu)造渲染樹(shù)和回流階段,我們知道了哪些節(jié)點(diǎn)是可見(jiàn)的,以及可見(jiàn)節(jié)點(diǎn)的樣式和具體的幾何信息(位置、大小),那么我們就可以將渲染樹(shù)的每個(gè)節(jié)點(diǎn)都轉(zhuǎn)換為屏幕上的實(shí)際像素,這個(gè)階段就叫做重繪節(jié)點(diǎn)。

    既然知道了瀏覽器的渲染過(guò)程后,我們就來(lái)探討下,何時(shí)會(huì)發(fā)生回流重繪。

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

    我們前面知道了,回流這一階段主要是計(jì)算節(jié)點(diǎn)的位置和幾何信息,那么當(dāng)頁(yè)面布局和幾何信息發(fā)生變化的時(shí)候,就需要回流。比如以下情況:

    • 添加或刪除可見(jiàn)的DOM元素
    • 元素的位置發(fā)生變化
    • 元素的尺寸發(fā)生變化(包括外邊距、內(nèi)邊框、邊框大小、高度和寬度等)
    • 內(nèi)容發(fā)生變化,比如文本變化或圖片被另一個(gè)不同尺寸的圖片所替代。
    • 頁(yè)面一開(kāi)始渲染的時(shí)候(這肯定避免不了)
    • 瀏覽器的窗口尺寸變化(因?yàn)榛亓魇歉鶕?jù)視口的大小來(lái)計(jì)算元素的位置和大小的)

    注意:回流一定會(huì)觸發(fā)重繪,而重繪不一定會(huì)回流

    根據(jù)改變的范圍和程度,渲染樹(shù)中或大或小的部分需要重新計(jì)算,有些改變會(huì)觸發(fā)整個(gè)頁(yè)面的重排,比如,滾動(dòng)條出現(xiàn)的時(shí)候或者修改了根節(jié)點(diǎn)。

    瀏覽器的優(yōu)化機(jī)制

    現(xiàn)代的瀏覽器都是很聰明的,由于每次重排都會(huì)造成額外的計(jì)算消耗,因此大多數(shù)瀏覽器都會(huì)通過(guò)隊(duì)列化修改并批量執(zhí)行來(lái)優(yōu)化重排過(guò)程。瀏覽器會(huì)將修改操作放入到隊(duì)列里,直到過(guò)了一段時(shí)間或者操作達(dá)到了一個(gè)閾值,才清空隊(duì)列。但是!當(dāng)你獲取布局信息的操作的時(shí)候,會(huì)強(qiáng)制隊(duì)列刷新,比如當(dāng)你訪問(wèn)以下屬性或者使用以下方法:

    • offsetTop、offsetLeft、offsetWidth、offsetHeight
    • scrollTop、scrollLeft、scrollWidth、scrollHeight
    • clientTop、clientLeft、clientWidth、clientHeight
    • getComputedStyle()
    • getBoundingClientRect
    • 具體可以訪問(wèn)這個(gè)網(wǎng)站:https://gist.github.com/paulirish/5d52fb081b3570c81e3a

    以上屬性和方法都需要返回最新的布局信息,因此瀏覽器不得不清空隊(duì)列,觸發(fā)回流重繪來(lái)返回正確的值。因此,我們?cè)谛薷臉邮降臅r(shí)候,**最好避免使用上面列出的屬性,他們都會(huì)刷新渲染隊(duì)列。**如果要使用它們,最好將值緩存起來(lái)。

    減少回流和重繪

    好了,到了我們今天的重頭戲,前面說(shuō)了這么多背景和理論知識(shí),接下來(lái)讓我們談?wù)勅绾螠p少回流和重繪。

    最小化重繪和重排

    由于重繪和重排可能代價(jià)比較昂貴,因此最好就是可以減少它的發(fā)生次數(shù)。為了減少發(fā)生次數(shù),我們可以合并多次對(duì)DOM和樣式的修改,然后一次處理掉。考慮這個(gè)例子

    const el = document.getElementById('test'); el.style.padding = '5px'; el.style.borderLeft = '1px'; el.style.borderRight = '2px';

    例子中,有三個(gè)樣式屬性被修改了,每一個(gè)都會(huì)影響元素的幾何結(jié)構(gòu),引起回流。當(dāng)然,大部分現(xiàn)代瀏覽器都對(duì)其做了優(yōu)化,因此,只會(huì)觸發(fā)一次重排。但是如果在舊版的瀏覽器或者在上面代碼執(zhí)行的時(shí)候,有其他代碼訪問(wèn)了布局信息(上文中的會(huì)觸發(fā)回流的布局信息),那么就會(huì)導(dǎo)致三次重排。

    因此,我們可以合并所有的改變?nèi)缓笠来翁幚?#xff0c;比如我們可以采取以下的方式:

    • 使用cssText
      const el = document.getElementById('test'); el.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px;';
    • 修改CSS的class
      const el = document.getElementById('test'); el.className += ' active';

    批量修改DOM

    當(dāng)我們需要對(duì)DOM對(duì)一系列修改的時(shí)候,可以通過(guò)以下步驟減少回流重繪次數(shù):

  • 使元素脫離文檔流
  • 對(duì)其進(jìn)行多次修改
  • 將元素帶回到文檔中。
  • 該過(guò)程的第一步和第三步可能會(huì)引起回流,但是經(jīng)過(guò)第一步之后,對(duì)DOM的所有修改都不會(huì)引起回流,因?yàn)樗呀?jīng)不在渲染樹(shù)了。

    有三種方式可以讓DOM脫離文檔流:

    • 隱藏元素,應(yīng)用修改,重新顯示
    • 使用文檔片段(document fragment)在當(dāng)前DOM之外構(gòu)建一個(gè)子樹(shù),再把它拷貝回文檔。
    • 將原始元素拷貝到一個(gè)脫離文檔的節(jié)點(diǎn)中,修改節(jié)點(diǎn)后,再替換原始的元素。

    考慮我們要執(zhí)行一段批量插入節(jié)點(diǎn)的代碼:

    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'); appendDataToElement(ul, data);

    如果我們直接這樣執(zhí)行的話,由于每次循環(huán)都會(huì)插入一個(gè)新的節(jié)點(diǎn),會(huì)導(dǎo)致瀏覽器回流一次。

    我們可以使用這三種方式進(jìn)行優(yōu)化:

    隱藏元素,應(yīng)用修改,重新顯示

    這個(gè)會(huì)在展示和隱藏節(jié)點(diǎn)的時(shí)候,產(chǎn)生兩次重繪

    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';

    使用文檔片段(document fragment)在當(dāng)前DOM之外構(gòu)建一個(gè)子樹(shù),再把它拷貝回文檔

    const ul = document.getElementById('list'); const fragment = document.createDocumentFragment(); appendDataToElement(fragment, data); ul.appendChild(fragment);

    將原始元素拷貝到一個(gè)脫離文檔的節(jié)點(diǎn)中,修改節(jié)點(diǎn)后,再替換原始的元素。

    const ul = document.getElementById('list'); const clone = ul.cloneNode(true); appendDataToElement(clone, data); ul.parentNode.replaceChild(clone, ul);

    對(duì)于上述那種情況,我寫了一個(gè)demo來(lái)測(cè)試修改前和修改后的性能。然而實(shí)驗(yàn)結(jié)果不是很理想。

    原因:原因其實(shí)上面也說(shuō)過(guò)了,瀏覽器會(huì)使用隊(duì)列來(lái)儲(chǔ)存多次修改,進(jìn)行優(yōu)化,所以對(duì)這個(gè)優(yōu)化方案,我們其實(shí)不用優(yōu)先考慮。

    避免觸發(fā)同步布局事件

    上文我們說(shuō)過(guò),當(dāng)我們?cè)L問(wèn)元素的一些屬性的時(shí)候,會(huì)導(dǎo)致瀏覽器強(qiáng)制清空隊(duì)列,進(jìn)行強(qiáng)制同步布局。舉個(gè)例子,比如說(shuō)我們想將一個(gè)p標(biāo)簽數(shù)組的寬度賦值為一個(gè)元素的寬度,我們可能寫出這樣的代碼:

    function initP() {for (let i = 0; i < paragraphs.length; i++) {paragraphs[i].style.width = box.offsetWidth + 'px';} }

    這段代碼看上去是沒(méi)有什么問(wèn)題,可是其實(shí)會(huì)造成很大的性能問(wèn)題。在每次循環(huán)的時(shí)候,都讀取了box的一個(gè)offsetWidth屬性值,然后利用它來(lái)更新p標(biāo)簽的width屬性。這就導(dǎo)致了每一次循環(huán)的時(shí)候,瀏覽器都必須先使上一次循環(huán)中的樣式更新操作生效,才能響應(yīng)本次循環(huán)的樣式讀取操作。每一次循環(huán)都會(huì)強(qiáng)制瀏覽器刷新隊(duì)列。我們可以優(yōu)化為:

    const width = box.offsetWidth; function initP() {for (let i = 0; i < paragraphs.length; i++) {paragraphs[i].style.width = width + 'px';} }

    同樣,我也寫了個(gè)demo來(lái)比較兩者的性能差異。你可以自己點(diǎn)開(kāi)這個(gè)demo體驗(yàn)下。這個(gè)對(duì)比差距就比較明顯。

    對(duì)于復(fù)雜動(dòng)畫效果,使用絕對(duì)定位讓其脫離文檔流

    對(duì)于復(fù)雜動(dòng)畫效果,由于會(huì)經(jīng)常的引起回流重繪,因此,我們可以使用絕對(duì)定位,讓它脫離文檔流。否則會(huì)引起父元素以及后續(xù)元素頻繁的回流。這個(gè)我們就直接上個(gè)例子。

    打開(kāi)這個(gè)例子后,我們可以打開(kāi)控制臺(tái),控制臺(tái)上會(huì)輸出當(dāng)前的幀數(shù)(雖然不準(zhǔn))。

    從上圖中,我們可以看到,幀數(shù)一直都沒(méi)到60。這個(gè)時(shí)候,只要我們點(diǎn)擊一下那個(gè)按鈕,把這個(gè)元素設(shè)置為絕對(duì)定位,幀數(shù)就可以穩(wěn)定60。

    css3硬件加速(GPU加速):

    比起考慮如何減少回流重繪,我們更期望的是,根本不要回流重繪。這個(gè)時(shí)候,css3硬件加速就閃亮登場(chǎng)啦!!

    劃重點(diǎn):使用css3硬件加速,可以讓transform、opacity、filters這些動(dòng)畫不會(huì)引起回流重繪 。但是對(duì)于動(dòng)畫的其它屬性,比如background-color這些,還是會(huì)引起回流重繪的,不過(guò)它還是可以提升這些動(dòng)畫的性能。

    本篇文章只討論如何使用,暫不考慮其原理,之后有空會(huì)另外開(kāi)篇文章說(shuō)明。

    如何使用

    常見(jiàn)的觸發(fā)硬件加速的css屬性:

    • transform
    • opacity
    • filters
    • Will-change

    效果

    我們可以先看個(gè)例子。我通過(guò)使用chrome的Performance捕獲了一段時(shí)間的回流重繪情況,實(shí)際結(jié)果如下圖:

    從圖中我們可以看出,在動(dòng)畫進(jìn)行的時(shí)候,沒(méi)有發(fā)生任何的回流重繪。如果感興趣你也可以自己做下實(shí)驗(yàn)。

    重點(diǎn)

    • 使用css3硬件加速,可以讓transform、opacity、filters這些動(dòng)畫不會(huì)引起回流重繪
    • 對(duì)于動(dòng)畫的其它屬性,比如background-color這些,還是會(huì)引起回流重繪的,不過(guò)它還是可以提升這些動(dòng)畫的性能。

    css3硬件加速的坑

    • 如果你為太多元素使用css3硬件加速,會(huì)導(dǎo)致內(nèi)存占用較大,會(huì)有性能問(wèn)題。
    • 在GPU渲染字體會(huì)導(dǎo)致抗鋸齒無(wú)效。這是因?yàn)镚PU和CPU的算法不同。因此如果你不在動(dòng)畫結(jié)束的時(shí)候關(guān)閉硬件加速,會(huì)產(chǎn)生字體模糊。
    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的dev 中 gridcontrol1 滚动条重绘_浏览器的重绘和回流(Repaint amp; Reflow)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 91精品久久香蕉国产线看观看 | 邻家有女4完整版电影观看 欧美偷拍另类 | 成年人免费在线视频 | 国产精品羞羞答答在线 | 黄色av网站网址 | 国产又粗又猛又爽又黄的视频小说 | 国产电影一区二区三区爱妃记 | 91成人免费看 | 日韩精品一区中文字幕 | 午夜久久视频 | 亚洲一级在线观看 | 蜜臀久久精品久久久久 | 手机看片久久久 | 欧美三级又粗又硬 | 中文字幕乱码在线人视频 | 黑人玩弄人妻一区二区三区影院 | 香蕉久久一区二区三区 | 成年人网站av | 伊人色综合网 | 成人三级晚上看 | 久草新免费 | 网站在线看 | 精品一区二区三区视频在线观看 | 波多野结衣大片 | 亚洲情区 | 久久久久在线视频 | caoporen超碰| 日本精品一二区 | 神秘电影永久入口 | 欧美人与禽zozzo禽性配 | 国产女人精品 | 日韩一级精品 | japanese国产在线| 成人免费看片98 | 国产精品久久久久久久一区二区 | 瑟瑟视频在线 | 国产原创一区 | 99久久精品国产一区色 | 亚洲国产成人精品女人久久 | 天天夜夜人人 | 国产精品 欧美精品 | 国产123在线 | 日本视频网址 | 91一区在线观看 | www..com色 | 亚州中文字幕 | 伊人66 | 天堂视频中文在线 | 色在线综合| 精品欧美黑人一区二区三区 | 日韩中文字幕在线观看视频 | 日本在线视频免费观看 | 伊人久久大香 | 成人手机看片 | 日韩欧美有码 | 亚洲欧美日韩激情 | 欧美国产不卡 | 佐佐木明希av在线 | 在线精品播放 | 日日噜噜夜夜狠狠久久丁香五月 | 美女的诞生免费观看在线高清 | 潮喷失禁大喷水无码 | 中文字幕97| 99国产免费 | 我们俩电影网mp4动漫官网 | 怡红院成人网 | 深夜视频一区二区 | 绿帽h啪肉np辣文 | 亚洲天堂首页 | 色哟哟视频在线观看 | 偷偷在线观看免费高清av | 色香五月 | 无遮挡裸光屁屁打屁股男男 | 日韩午夜 | 精品妇女一区二区三区 | 国产青青视频 | 337p粉嫩色噜噜噜大肥臀 | 亚洲国产免费 | 最新中文字幕第一页 | 一区二区视频播放 | 色在线视频观看 | 日韩最新视频 | 欧美老女人xx| 蜜桃免费av | 日韩久久久久久久 | 九九黄色片 | 日本精品视频在线播放 | 在线播放少妇奶水过盛 | 精品国产网站 | 成人一级影片 | 国产精品麻豆果冻传媒在线播放 | 一区二区三区欧美在线 | 国产成人亚洲精品 | 免费看一级 | 国产观看 | 国产成人精品白浆久久69 | www色com| 日韩激情网站 | 欧美三级成人 |