細談頁面回流與重繪

你將了解到:

什么是回流
什么是重繪
回流何時發生
重繪何時發生
如何避免回流和重繪
復制代碼

帶著上面的問題,我們一探究竟

什么是回流

回流:英文是reflow

當render tree中的一部分(或全部),因為元素的規模尺寸、布局、隱藏等改變
而需要重新構建,這就是回流(reflow)
復制代碼
  • 每個頁面至少回流一次,即頁面首次加載
  • 回流時,瀏覽器會使渲染樹中受到影響的部分失效,并重新構造這部分渲染樹
  • 回流完成后,瀏覽器會重新繪制受影響的部分,是重繪過程

什么是重繪

重繪:英文是repaints

當render tree中的一些元素需要更新屬性,而這些屬性只是影響元素的外
觀、風格,而不影響布局(例如:background-color),則稱為重繪(repaints)
復制代碼

特點:回流必將引起重繪,重繪不一定引起回流 回流比重繪的代價更高

回流何時發生

當頁面布局和幾何屬性改變時就需要回流

下述情況會發生瀏覽器回流:

(1)添加或者刪除可見的DOM元素;
(2)元素位置改變;
(3)元素尺寸改變——邊距、填充、邊框、寬度和高度
(4)內容改變——比如文本改變或者圖片大小改變而引起的計算值寬度和高度改變;
(5)頁面渲染初始化;
(6)瀏覽器窗口尺寸改變——resize事件發生時;
復制代碼
let box = document.getElementById("box").style;
box.padding = "2px";   // 回流+重繪
box.border = "1px solid red";  // 再一次 回流+重繪
box.fontSize = "14px";    // 回流+重繪
document.getElementById("box").appendChild(document.createTextNode('abc!'));
復制代碼

重繪何時發生

元素的屬性或者樣式發生變化。

let box = document.getElementById("box").style;
box.color = "red";    // 重繪
box.backgroud-color = "blue";    // 重繪
document.getElementById("box").appendChild(document.createTextNode('abc!'));
復制代碼

因回流的開銷較大,如果每個操作都去回流重繪的話,瀏覽器可能就會受不了。所以很多瀏覽器都會優化這些操作。

多次的回流、重繪變成一次回流重繪:

瀏覽器會維護1個隊列,把所有會引起回流、重繪的操作放入這個隊列,等
隊列中的操作到了一定的數量或者到了一定的時間間隔,瀏覽器就會flush
隊列,進行一個批處理。
復制代碼

但是有時上面的方法會失效,原因是:

有些情況,當請求向瀏覽器請求一些style信息的時候,就會讓瀏覽器強制flush隊列,比如:(1)offsetTop, offsetLeft, offsetWidth, offsetHeight
(2) scrollTop/Left/Width/Height
(3)clientTop/Left/Width/Height
(4)width,height
(5)請求了getComputedStyle(), 或者 IE的 currentStyle
復制代碼

當你請求上面的一些屬性的時候,瀏覽器為了給你最精確的值,需要flush隊列,因為隊列中可能會有影響到這些值的操作。即使你獲取元素的布局和樣式信息跟最近發生或改變的布局信息無關,瀏覽器都會強行刷新渲染隊列。

這樣以來,瀏覽器的優化就顯得力不從心,所以我們需要一些方法,盡可能的避免或減少瀏覽器的回流、重繪

如何避免、減少回流和重繪

  • 減少對render tree的操作【合并多次多DOM和樣式的修改】
  • 減少對一些style信息的請求,盡量利用好瀏覽器的優化策略
(1)添加css樣式,而不是利用js控制樣式
(2)讓要操作的元素進行“離線處理”,處理完后一起更新當用DocumentFragment進行緩存操作,引發一次回流和重繪使用display:none技術,只引發兩次回流和重繪使用cloneNode(true or false)和replaceChild技術,引發一次回流和重繪
(3)直接改變className,如果動態改變樣式,則使用cssText(考慮沒有優化的瀏覽器)// badelem.style.left = x + "px";elem.style.top = y + "px";// goodelem.style.cssText += ";left: " + x + "px;top: " + y + "px;";
(4)不要經常訪問會引起瀏覽器flush隊列的屬性,如果你確實要訪問,利用緩存// badfor (var i = 0; i < len; i++) {el.style.left = el.offsetLeft + x + "px";el.style.top = el.offsetTop + y + "px";}// goodvar x = el.offsetLeft,y = el.offsetTop;for (var i = 0; i < len; i++) {x += 10;y += 10;el.style = x + "px";el.style = y + "px";}
(5)讓元素脫離動畫流,減少回流的Render Tree的規模$("#block1").animate({left:50});$("#block2").animate({marginLeft:50});
(6)將需要多次重排的元素,position屬性設為absolute或fixed,這樣此元素就脫離了文檔流,它的變化不會影響到其他元素。例如有動畫效果的元素就最好設置為絕對定位;
(7)避免使用table布局:盡量不要使用表格布局,如果沒有定寬表格一列的寬度由最寬的一列決定,那么很可能在最后一行的寬度超出之前的列寬,引起整體回流造成table可能需要多次計算才能確定好其在渲染樹中節點的屬性,通常要花3倍于同等元素的時間。
(8)盡量將需要改變DOM的操作一次完成let box = document.getElementById("box").style;// badbox.color = "red";    // 重繪box.size = "14px";    // 回流、重繪// goodbox.bord = '1px solid red'
(9)盡可能在DOM樹的最末端改變class,盡可能在DOM樹的里面改變class(可以限制回流的范圍)
(10)IE中避免使用JavaScript表達式
復制代碼

參考資料:

  • 前端進階(二)重繪和回流
  • 重繪與回流
  • 頁面的重繪與回流,以及如何優化

轉載于:https://juejin.im/post/5c87bd375188257e3e47fdc5

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/536827.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/536827.shtml
英文地址,請注明出處:http://en.pswp.cn/news/536827.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

安卓 java中改布局_android-選項卡布局中的地圖視圖throwing,java....

我創建了一個具有選項卡布局的應用程序,單擊選項卡后,我將打開一個使用Web視圖的新活動.另外另一個選項卡使用地圖視圖,列表視圖,圖像視圖.現在,我在Samsung Galaxy Y上安裝了我的應用程序-運行正常.當我在Samsung Galaxy Tab 2上安裝相同的應用程序時,當我第一次打開地圖視圖,…

怎么樣修改PuTTY的默認字體和字符集

1.在窗口標題上點擊右鍵&#xff0c;選擇 Change Settings...2.在打開的配置窗口左邊選擇 Appearance&#xff0c;在右邊點 Font settings 里面的 Change 按鈕&#xff0c;選擇好中文字體&#xff0c;比如&#xff1a;宋體、新宋體之類的3.選擇配置窗口左邊的 Translation&…

python 元組比較大小_為什么元組比列表更快?

所報道的“build設速度”比率只適用于常量元組(項目用文字表示)。 仔細觀察(并在機器上重復 – 只需在shell /命令窗口input命令&#xff01;)…&#xff1a;$ python3.1 -mtimeit -sx,y,z1,2,3 [x,y,z] 1000000 loops, best of 3: 0.379 usec per loop $ python3.1 -mtimeit […

windows軟鏈接的建立及刪除

2019獨角獸企業重金招聘Python工程師標準>>> 1.建立舉例 # 建立d:develop鏈接目錄&#xff0c;指向遠程的目標服務器上的e盤的對應目錄。 mklink /d d:\develop \\138.20.1.141\e$\develop# 建立d:develop鏈接目錄&#xff0c;指向遠程的目標服務器上的e盤的對應目錄…

php原生類,反序列化之PHP原生類的利用

正文文章圍繞著一個問題&#xff0c;如果在代碼審計中有反序列化點&#xff0c;但是在原本的代碼中找不到pop鏈該如何?N1CTF有一個無pop鏈的反序列化的題目&#xff0c;其中就是找到php內置類來進行反序列化。基礎知識首先還是來回顧一下序列化中的魔術方法&#xff0c;下面也…

Spectral Bounds for Sparse PCA: Exact and Greedy Algorithms[貪婪算法選特征]

目錄 概括Sparse PCA Formulation非常普遍的問題Optimality ConditionsEigenvalue Bounds算法代碼概括 這篇論文&#xff0c;不像以往的那些論文&#xff0c;構造優化問題&#xff0c;然后再求解這個問題&#xff08;一般都是凸化&#xff09;。而是&#xff0c;直接選擇某些特…

js php調用webservice,php調用web services兩種方法soap和curl

以http://www.webxml.com.cn/zh_cn/index.aspx一、使用soap調用//服務器支持soap擴展:/*Example 1:$client new SoapClient("http://fy.webxml.com.cn/webservices/EnglishChinese.asmx?wsdl");$parameters array("wordKey">"test");//中英…

JS基礎-3

1.for in 對象中有多少組鍵值對,我們的FOR IN 循環就遍歷多少次(不一定) 每一次循環KEY這個變量存儲的都是當前循環這組鍵對值的屬性名 1、KEY存儲的值都是字符串格式的(不管屬性名是否為數字) 2、在FOR IN 循環遍歷的時候&#xff0c;大部分瀏覽器都是先把對象中的鍵值對進行排…

Python常用的幾個函數

print()函數&#xff1a;用于打印輸出信息到控制臺。 input()函數&#xff1a;用于從控制臺獲取用戶輸入。 len()函數&#xff1a;用于獲取字符串、列表、元組、字典等對象的長度。 range()函數&#xff1a;用于生成一個整數序列&#xff0c;常用于循環中。 type()函數&…

數據結構——常見的定義

問題答案Ο標記法&#xff08;大Ο標記法&#xff09;是一種用于衡量算法時間復雜度的表示方法。它描述了算法在最壞情況下的運行時間增長率。當我們使用Ο標記法時&#xff0c;我們關注的是算法的上界&#xff0c;即算法的運行時間不會超過Ο(f(n))&#xff0c;其中 f(n) 是輸…

TikTok與環保:短視頻如何引領可持續生活方式?

在數字時代&#xff0c;社交媒體平臺扮演著塑造文化和價值觀的關鍵角色。而TikTok&#xff0c;作為一款全球短視頻平臺&#xff0c;不僅塑造著用戶的娛樂方式&#xff0c;還在悄然地引領著可持續生活方式的潮流。本文將深入探討TikTok與環保之間的關系&#xff0c;分析短視頻如…

Spring源碼分析---Bean 的生命周期 03

來源&#xff1a;Spring 3. Bean 的生命周期 自定義一個 SpringBoot 的主啟動類&#xff1a; SpringBootApplication public class A03Application {public static void main(String[] args) {ConfigurableApplicationContext context SpringApplication.run(A03Applicatio…

go-carbon v2.3.0 圣誕特別版發布,輕量級、語義化、對開發者友好的 Golang 時間處理庫

go-carbon v2.3.0 圣誕節特別版發布&#xff0c;這應該是 2023 年的最后一個版本&#xff0c;祝大家圣誕節快樂&#xff01; carbon 是一個輕量級、語義化、對開發者友好的 golang 時間處理庫&#xff0c;支持鏈式調用。 目前已被 awesome-go 收錄&#xff0c;如果您覺得不錯…

pytorch 實現 Restormer 主要模塊(多頭通道自注意力機制和門控制結構)

前面的博文讀論文&#xff1a;Restormer: Efficient Transformer for High-Resolution Image Restoration 介紹了 Restormer 網絡結構的網絡技術特點&#xff0c;本文用 pytorch 實現其中的主要網絡結構模塊。 1. MDTA(Multi-Dconv Head Transposed Attention&#xff1a;多頭…

選擇免費的SSL證書,還是付費的?

作為一個互聯網文章作者&#xff0c;我會根據具體的使用場景和需求來選擇SSL證書。通常情況下&#xff0c;如果是用于個人網站或者小型項目&#xff0c;我會傾向于選擇免費的SSL證書&#xff0c;比如 JoySSL提供的免費證書。這樣可以在不增加額外費用的情況下為網站提供安全的加…

靜態HTTP與CDN:如何優化內容分發

大家好&#xff0c;今天我們來聊聊靜態HTTP和CDN這對“黃金搭檔”。沒錯&#xff0c;就是那個讓你的網站內容像閃電一樣傳遍全球的CDN&#xff01; 首先&#xff0c;我們來了解一下靜態HTTP。它就像是那個老實可靠的郵差&#xff0c;每次都按時按點地把你的內容送到用戶手中。…

第二十一章博客

計算機應用實現了多臺計算機間的互聯&#xff0c;使得它們彼此之間能夠進行數據交流。網絡應用程序就是在已連接的不同計算機上運行的程序&#xff0c;這些程序借助于網絡協議&#xff0c;相互之間可以交換數據。編寫網絡應用程序前&#xff0c;首先必須明確所要使用的網絡協議…

Node.js中處理特殊字符的文件名,安全穩妥的方案

在Node.js中&#xff0c;通過path模塊提供的basename方法&#xff0c;我們可以輕松地從文件路徑中提取文件名。然而&#xff0c;這個方法在處理特殊字符時存在一些問題&#xff0c;因為它會對這些字符進行轉義&#xff0c;導致在不同操作系統上的兼容性問題。在這篇文章中&…

C++ boost planner_cond_.wait(lock) 報錯1225

1.如下程序段 boost unique_lock doesn’t own the mutex: Operation not permitted 問題&#xff1a; 其中makePlan是一個線程。這里的unlock導致錯誤這個報錯 boost unique_lock doesn’t own the mutex: Operation not permitted bool navigation::makePlan(){ //cv::named…

MySQL中如何快速定位占用CPU過高的SQL

作為DBA工作中都會遇到過數據庫服務器CPU飆升的場景&#xff0c;我們該如何快速定位問題&#xff1f;又該如何快速找到具體是哪個SQL引發的CPU異常呢&#xff1f;下面我們說兩個方法。聊聊MySQL中如何快速定位占用CPU過高的SQL。 技術人人都可以磨煉&#xff0c;但處理問題的思…