帶你認識什麼是“迴流重繪”

来源:https://www.cnblogs.com/huaweiyun/archive/2022/10/09/16772243.html
-Advertisement-
Play Games

摘要:要想減少迴流和重繪的次數,首先要瞭解迴流和重繪是如何觸發的。 本文分享自華為雲社區《前端頁面之“迴流重繪”》,作者:CoderBin。 “迴流重繪”是什麼? 在HTML中,每個元素都可以理解成一個盒子,在瀏覽器解析過程中,會涉及到迴流與重繪: 迴流:佈局引擎會根據各種樣式計算每個盒子在頁面上的 ...


摘要:要想減少迴流和重繪的次數,首先要瞭解迴流和重繪是如何觸發的。

本文分享自華為雲社區《前端頁面之“迴流重繪”》,作者:CoderBin。

“迴流重繪”是什麼?

在HTML中,每個元素都可以理解成一個盒子,在瀏覽器解析過程中,會涉及到迴流與重繪:

  • 迴流:佈局引擎會根據各種樣式計算每個盒子在頁面上的大小與位置;
  • 重繪:當計算好盒模型的位置、大小及其他屬性後,瀏覽器根據每個盒子特性進行繪製。

具體的瀏覽器解析渲染機制如下所示:

  • 解析HTML,生成DOM樹,解析CSS,生成CSSOM樹
  • 將DOM樹和CSSOM樹結合,生成渲染樹(Render Tree)
  • Layout(迴流):根據生成的渲染樹,進行迴流(Layout),得到節點的幾何信息(位置,大小)
  • Painting(重繪):根據渲染樹以及迴流得到的幾何信息,得到節點的絕對像素
  • Display:將像素髮送給GPU,展示在頁面上

在頁面初始渲染階段,迴流不可避免的觸發,可以理解成頁面一開始是空白的元素,後面添加了新的元素使頁面佈局發生改變。

當我們對 DOM 的修改引發了 DOM幾何尺寸的變化(比如修改元素的寬、高或隱藏元素等)時,瀏覽器需要重新計算元素的幾何屬性,然後再將計算的結果繪製出來。

當我們對 DOM的修改導致了樣式的變化(color或background-color),卻並未影響其幾何屬性時,瀏覽器不需重新計算元素的幾何屬性、直接為該元素繪製新的樣式,這裡就僅僅觸發了迴流。

如何觸發

要想減少迴流和重繪的次數,首先要瞭解迴流和重繪是如何觸發的。

迴流觸發時機

迴流這一階段主要是計算節點的位置和幾何信息,那麼當頁面佈局和幾何信息發生變化的時候,就需要迴流,如下麵情況:

  • 添加或刪除可見的DOM元素
  • 元素的位置發生變化
  • 元素的尺寸發生變化(包括外邊距、內邊框、邊框大小、高度和寬度等)
  • 內容發生變化,比如文本變化或圖片被另一個不同尺寸的圖片所替代
  • 頁面一開始渲染的時候(這避免不了)
  • 瀏覽器的視窗尺寸變化(因為迴流是根據視口的大小來計算元素的位置和大小的)

還有一些容易被忽略的操作:獲取一些特定屬性的值。

offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight

這些屬性有一個共性,就是需要通過即時計算得到。因此瀏覽器為了獲取這些值,也會進行迴流。

除此還包括getComputedStyle方法,原理是一樣的。

重繪觸發時機

觸發迴流一定會觸發重繪

可以把頁面理解為一個黑板,黑板上有一朵畫好的小花。現在我們要把這朵從左邊移到了右邊,那我們要先確定好右邊的具體位置,畫好形狀(迴流),再畫上它原有的顏色(重繪)。

除此之外還有一些其他引起重繪行為:

  • 顏色的修改
  • 文本方向的修改
  • 陰影的修改

瀏覽器優化機制

由於每次重排都會造成額外的計算消耗,因此大多數瀏覽器都會通過隊列化修改並批量執行來優化重排過程。瀏覽器會將修改操作放入到隊列里,直到過了一段時間或者操作達到了一個閾值,才清空隊列。

當你獲取佈局信息的操作的時候,會強制隊列刷新,包括前面講到的offsetTop等方法都會返回最新的數據。

因此瀏覽器不得不清空隊列,觸發迴流重繪來返回正確的值。

如何減少

我們瞭解瞭如何觸發迴流和重繪的場景,下麵給出避免迴流的經驗:

  • 如果想設定元素的樣式,通過改變元素的 class 類名 (儘可能在 DOM 樹的最裡層)
  • 避免設置多項內聯樣式
  • 應用元素的動畫,使用 position 屬性的 fixed 值或 absolute 值(如前文示例所提)
  • 避免使用 table 佈局,table 中每個元素的大小以及內容的改動,都會導致整個 table 的重新計算
  • 對於那些複雜的動畫,對其設置 position: fixed/absolute,儘可能地使元素脫離文檔流,從而減少對其他元素的影響
  • 使用css3硬體加速,可以讓transform、opacity、filters這些動畫不會引起迴流重繪
  • 避免使用 CSS 的 JavaScript 表達式

在使用 JavaScript 動態插入多個節點時, 可以使用DocumentFragment. 創建後一次插入. 就能避免多次的渲染性能。

但有時候,我們會無可避免地進行迴流或者重繪,我們可以更好使用它們

例如,多次修改一個把元素佈局的時候,我們很可能會如下操作。

const el = document.getElementById('el')
for(let i=0;i<10;i++) {
 el.style.top = el.offsetTop + 10 + "px";
 el.style.left = el.offsetLeft + 10 + "px";
}

每次迴圈都需要獲取多次offset屬性,比較糟糕,可以使用變數的形式緩存起來,待計算完畢再提交給瀏覽器發出重計算請求。

// 緩存offsetLeft與offsetTop的值
const el = document.getElementById('el') 
let offLeft = el.offsetLeft, offTop = el.offsetTop
// 在JS層面進行計算
for(let i=0;i<10;i++) {
 offLeft += 10
 offTop += 10
}
// 一次性將計算結果應用到DOM上
el.style.left = offLeft + "px"
el.style.top = offTop + "px"

我們還可避免改變樣式,使用類名去合併樣式。

const container = document.getElementById('container')
container.style.width = '100px'
container.style.height = '200px'
container.style.border = '10px solid red'
container.style.color = 'red'

使用類名去合併樣式

<style>
 .basic_style {
 width: 100px;
 height: 200px;
 border: 10px solid red;
 color: red;
  }
</style>
<script>
 const container = document.getElementById('container')
 container.classList.add('basic_style')
</script>

前者每次單獨操作,都去觸發一次渲染樹更改(新瀏覽器不會),都去觸發一次渲染樹更改,從而導致相應的迴流與重繪過程,合併之後,等於我們將所有的更改一次性發出。

我們還可以通過通過設置元素屬性display: none,將其從頁面上去掉,然後再進行後續操作,這些後續操作也不會觸發迴流與重繪,這個過程稱為離線操作。

 

點擊關註,第一時間瞭解華為雲新鮮技術~


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1)對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。 2)應儘量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。 3)應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引 ...
  • 存儲引擎 1.基本介紹 基本介紹 MySQL的表類型由存儲引擎(Storage Engines)決定,主要包括MyISAM、innoDB、Memory等 MySQL數據表主要支持六種類型,分別是:CSV,Memory,ARCHIVE,MRG_MYISAM,MYISAM,InnoBDB。 這六種又分為 ...
  • 本期我們帶大家回顧一下無倦同學的直播分享《ChunJun類載入器隔離》,ChunJun類載入器隔離的方案是我們近期探索的一個新方案,這個方案目前還不是非常成熟,希望能藉由此次分享與大家一起探討下這方案,如果大家有一些新的想法歡迎大家在github上給我提issue或者pr。 一、Java 類載入器解 ...
  • 摘要:GaussDB(for Redis)推出了雙活解決方案,基於GaussDB NoSQL統一架構,通過兩個資料庫實例之間的數據同步,達成數據的一致性。 本文分享自華為雲社區《【雲圖說】一張圖瞭解GaussDB(for Redis)雙活解決方案》,作者: 高斯Redis官方博客。 網路異常、電力故 ...
  • 摘要:本文從零開始引導與大家一起學習圖知識。希望大家可以通過本教程學習如何使用圖資料庫與圖計算引擎。本篇將以華為雲圖引擎服務來輔助大家學習如何使用圖資料庫與圖計算引擎。 本文分享自華為雲社區《從零開始學Graph Database(1)》,作者:弓乙 。 基礎概念 什麼是圖? 首先,我們需要明確圖 ...
  • 這裡會介紹ClickHouse幾種資料庫引擎,已經對應的特點和應用的場景。資料庫引擎允許您處理數據表。預設情況下,ClickHouse使用Atomic資料庫引擎。它提供了可配置的table engines和SQL dialect。 目前的資料庫引擎: MySQL MaterializeMySQL L ...
  • 我們平時會寫各種各樣或簡單或複雜的sql語句,提交後就會得到我們想要的結果集。比如sql語句,”select * from t_user where user_id > 10;”,意在從表t_user中篩選出user_id大於10的所有記錄。你有沒有想過從一條sql到一個結果集,這中間經歷了多少坎坷... ...
  • 如何使用KrpanoToolJS在瀏覽器切圖 框架DEMO 框架源碼地址 【獨闢蹊徑】逆推Krpano切圖演算法,實現在瀏覽器切多層級瓦片圖 一、功能介紹 在瀏覽器中將全景圖轉為立方體圖、多層級瓦片圖 備註: 切圖的邏輯、縮略圖、預覽圖均以krpano為標準,如果是使用krpano來開發全景的,可以直 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...