JS的重繪、回流

1、什么是重繪、回流

  • 重繪(repaint):當(dāng)元素樣式的改變不影響頁面布局時(shí),比如元素的顏色,瀏覽器將對(duì)元素進(jìn)行的更新,稱之為重繪。

    常見的重繪操作有:
    1,改變?cè)仡伾?br> 2,改變?cè)乇尘吧?……

  • 回流(reflow):也叫做重排。當(dāng)元素的尺寸或者位置發(fā)生了變化,就需要重新計(jì)算渲染樹,這就是回流,比如元素的寬高、位置,瀏覽器會(huì)重新渲染頁面,稱為回流,又叫重排(layout)。

    回流是影響瀏覽器性能的關(guān)鍵因素。因?yàn)?code>一個(gè)元素的回流,可能會(huì)導(dǎo)致了其所有子元素以及緊隨其后的節(jié)點(diǎn)、或祖先節(jié)點(diǎn)元素,或部分頁面或整個(gè)頁面的回流

  • 關(guān)系:回流必定會(huì)觸發(fā)重繪,重繪不一定會(huì)觸發(fā)回流。重繪的開銷較小,回流的代價(jià)較高

DOM 樣式發(fā)生了變化,但沒有影響到頁面布局時(shí),會(huì)觸發(fā)重繪,而不會(huì)觸發(fā)回流。
重繪由于 DOM 位置信息不需要更新,省去了布局過程,因而性能上優(yōu)于回流

2、導(dǎo)致回流的操作

  • 1、頁面的首次渲染

  • 2、瀏覽器的窗口大小發(fā)生變化

  • 3、元素的尺寸或者位置發(fā)生變化

    • 盒子模型相關(guān)屬性的改變:
      width、height、padding、border、margin、display、border-width、min-height
    • 定位屬性及浮動(dòng)元素位置的心跡:
      top、right、bottom、left、position、float、clear
    • display屬性值的變化
    • 元素的字體大小、行內(nèi)屬性發(fā)生變化:
      font-size、line-height
  • 4、查詢?cè)氐奈恢脤傩曰蛲ㄟ^某些方法獲取元素尺寸時(shí)

    1、offsetTop、offsetLeft、offsetWidth、offsetHeight 
    2、scrollTop、scrollLeft、scrollWidth、scrollHeight 
    3、clientTop、clientLeft、clientWidth、clientHeight 
    4、width、height 
    5、getComputedStyle() 
    6、getBoundingClientRect()
    
    

    但當(dāng)你獲取元素位置信息的時(shí)候,隊(duì)列中可能有會(huì)影響元素位置的操作,
    即使沒有,瀏 覽器也會(huì)強(qiáng)制清空隊(duì)列,觸發(fā)回流與重繪來確保返回正確的值

  • 5、DOM 節(jié)點(diǎn)移動(dòng)、刪除、增加

當(dāng)觸發(fā)回流時(shí),會(huì)導(dǎo)致周圍的 DOM 元素重新排列,它的影響范圍有兩種:

  • 全局范圍:從根節(jié)點(diǎn)開始,對(duì)整個(gè)渲染樹進(jìn)行重新布局
  • 局部范圍:對(duì)渲染樹的某部分或者一個(gè)渲染對(duì)象進(jìn)行重新布局

3、只觸發(fā)頁面重繪的屬性

  • 顏色相關(guān)的樣式:color、border-color、background-color
  • 圖片相關(guān)的閉幕式: background-image、image
  • 邊框相關(guān)的樣式:border-style、border-radius、
  • 隱藏相關(guān)的:visibility、opacity
  • 其它:box-shadow、text-decoration

4、如何減少重繪和回流

4.1、從Javascript角度來看
  • 1、避免頻繁操作style
    可以通過class一次性修改樣式, 而非通過style一個(gè)一個(gè)修改,這樣減少回流與重繪的次數(shù)

  • 2、避免頻繁的DOM 操作

    • 修改節(jié)點(diǎn)時(shí) ,采用離線模式,離線模式就是克隆要操作的結(jié)點(diǎn), 操作后再與原始結(jié)點(diǎn)交換, 這樣可以減少dom的操作次數(shù)`·
    • 新增、刪除、修改、查找節(jié)點(diǎn)時(shí)對(duì)同一個(gè)節(jié)點(diǎn)需多次插入新的dom節(jié)點(diǎn)時(shí),可以使用文檔片段documentFragment,先插入到文檔片段中,再把文檔片段一次性插入到指定節(jié)點(diǎn)中,因?yàn)槲臋n片段存在于內(nèi)存中,并不在DOM樹中,所以將子元素插入到文檔片段時(shí)不會(huì)引起頁面回流。因此,使用文檔片段通常會(huì)帶來更好的性能。
    • 將 DOM 的多個(gè)讀操作(或者寫操作)放在一起,而不是讀寫操作穿插著寫。這得益于瀏覽器的渲染隊(duì)列機(jī)制。

    瀏覽器的渲染隊(duì)列機(jī)制:
    瀏覽器會(huì)將所有的回流、重繪的操作放在一個(gè)隊(duì)列中,當(dāng)隊(duì)列中的操作到了一定的數(shù)量或者到了一定的時(shí)間間隔,瀏覽器就會(huì)對(duì)隊(duì)列進(jìn)行批處理。這樣就會(huì)讓多次的回流、重繪變成一次回流重繪。

  • 3、避免頻繁讀取會(huì)引發(fā)回流/重繪的屬性,如果確實(shí)需要多次使用,就用一個(gè) 變量緩存起來。
    不要頻繁地去獲取某個(gè)dom節(jié)點(diǎn)的位置屬性信息(如offsetWidth,offsetHeight, clientWidth, clientHeight),因?yàn)檫@樣會(huì)大大消耗瀏覽器的計(jì)算性能。(回流,就是利用瀏覽器的計(jì)算性能,重新計(jì)算容器的位置

    for(var i = 0;i<=10;i++){
       var body = document.getElementsByTagName('body')[0]
       var h = body.offsetHeight;
    }
    
    

    瀏覽器回流的緩沖機(jī)制,即多個(gè)回流會(huì)保存在一個(gè)棧里面,當(dāng)這個(gè)棧滿了瀏覽器便會(huì)一次性觸發(fā)所有樣式的更改且刷新這個(gè)棧。但是如果你多次獲取這些元素的實(shí)際樣式,瀏覽器為了給你一個(gè)準(zhǔn)確的答案便會(huì)不停刷新這個(gè)緩沖棧,導(dǎo)致頁面回流增加。所以為了避免這個(gè)問題,應(yīng)該用一個(gè)變量保存在循環(huán)體外。offsetWidth/offsetHeight,會(huì)強(qiáng)制刷新緩沖機(jī)制

`4.2、從Html / CSS角度來看
  • 1、對(duì)動(dòng)畫效果,使用 absolute 或 fixed,使元素脫離文檔流,避免影響其他元素的布局。
  • 2、避免使用 table布局,可能很小的一個(gè)小改動(dòng)會(huì)造成整個(gè) table 的重新布局。
  • 3、修改 DOM 時(shí),盡可能只修改最末端的節(jié)點(diǎn),這樣減少其影響范圍
  • 4、html不要嵌套太深, 否則會(huì)加大對(duì)頁面布局的計(jì)算消耗
  • 5、css避免設(shè)置多層內(nèi)聯(lián)樣式,CSS 選擇符從右往左匹配查找,避免節(jié)點(diǎn)層級(jí)過多
  • 6、使用 visibility 替換 display: none,因?yàn)榍罢咧粫?huì)引起重繪,后者會(huì)引發(fā)回流

參考鏈接:https://www.cnblogs.com/jianxian/p/12077584.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容