前端面試查漏補缺--(五) 渲染機制及重繪和迴流

前言

本系列最開始是爲了本身面試準備的.後來發現整理愈來愈多,差很少有十二萬字符,最後決定仍是分享出來給你們.html

爲了分享整理出來,花費了本身大量的時間,起碼是隻本身用的三倍時間.若是喜歡的話,歡迎收藏,關注我!謝謝!前端

文章連接

合集篇:

前端面試查漏補缺--Index篇(12萬字符合集) 包含目前已寫好的系列其餘十幾篇文章.後續新增值文章不會再在每篇添加連接,強烈建議議點贊,關注合集篇!!!!,謝謝!~vue

後續更新計劃

後續還會繼續添加設計模式,前端工程化,項目流程,部署,閉環,vue常考知識點 等內容.若是以爲內容不錯的話歡迎收藏,關注我!謝謝!面試

求一分內推

目前本人也在準備跳槽,但願各位大佬和HR小姐姐能夠內推一份靠譜的武漢 前端崗位!郵箱:bupabuku@foxmail.com.謝謝啦!~算法

渲染機制

渲染步驟

瀏覽器的渲染機制通常分爲如下幾個步驟:設計模式

    1. 處理 HTML 並構建 DOM 樹。
    1. 處理 CSS 構建 CSSOM 樹。
    1. 將 DOM 與 CSSOM 合併成一個渲染樹。
    1. 根據渲染樹來佈局,計算每一個節點的位置。
    1. 調用 GPU 繪製,合成圖層,顯示在屏幕上。

注意:前端工程化

  • 在構建 CSSOM 樹時,會阻塞渲染,直至 CSSOM 樹構建完成。而且構建 CSSOM 樹是一個十分消耗性能的過程,因此應該儘可能保證層級扁平,減小過分層疊,越是具體的 CSS 選擇器,執行速度越慢
  • 當 HTML 解析到 script 標籤時,會暫停構建 DOM, 完成後纔會從暫停的地方從新開始。也就是說,若是你想首屏渲染的越快,就越不該該在首屏就加載 JS 文件。而且 CSS 也會影響 JS 的執行,只有當解析完樣式表纔會執行 JS,因此也能夠認爲這種狀況下,CSS 也會暫停構建 DOM。

Load 和 DOMContentLoaded 區別

  • Load 事件觸發表明頁面中的 DOM,CSS,JS,圖片已經所有加載完畢。
  • DOMContentLoaded 事件觸發表明初始的 HTML 被徹底加載和解析,不須要等待 CSS,JS,圖片加載。

圖層

通常來講,能夠把普通文檔流當作一個圖層。特定的屬性能夠生成一個新的圖層。不一樣的圖層渲染互不影響,因此對於某些頻繁須要渲染的建議單獨生成一個新圖層,提升性能。但也不能生成過多的圖層,會引發副作用。跨域

經過如下幾個經常使用屬性能夠生成新圖層瀏覽器

  • 3D 變換:translate3dtranslateZ
  • will-change
  • videoiframe 標籤
  • 經過動畫實現的 opacity 動畫轉換
  • position: fixed

重繪(Repaint)和迴流(Reflow)

概念

重繪和迴流是渲染步驟中的一小節,可是這兩個步驟對於性能影響很大。緩存

  • 重繪是 當節點須要更改外觀而不會影響佈局的,好比改變 color、background-color、visibility等就叫稱爲重繪
  • 迴流是 佈局或者幾何屬性須要改變 就稱爲迴流。

注意: 迴流一定會發生重繪,重繪不必定會引起迴流。迴流所需的成本比重繪高的多,改變深層次的節點極可能致使父節點的一系列迴流。

會致使迴流的操做:

  • 頁面首次渲染
  • 瀏覽器窗口大小發生改變
  • 元素尺寸或位置發生改變
  • 元素內容變化(文字數量或圖片大小等等)
  • 元素字體大小變化
  • 添加或者刪除可見DOM元素
  • 激活CSS僞類(例如::hover
  • 查詢某些屬性或調用某些方法

一些經常使用且會致使迴流的屬性和方法:

  • clientWidthclientHeightclientTopclientLeft
  • offsetWidthoffsetHeightoffsetTopoffsetLeft
  • scrollWidthscrollHeightscrollTopscrollLeft
  • scrollIntoView()scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()

重繪和迴流與Event loop關係

不少人不知道的是,重繪和迴流其實和 Event loop 有關。

  1. 當 Event loop 執行完 Microtasks 後,會判斷 document 是否須要更新。由於瀏覽器是 60Hz 的刷新率,每 16ms 纔會更新一次。
  2. 而後判斷是否有 resize 或者 scroll ,有的話會去觸發事件,因此 resize 和 scroll 事件也是至少 16ms 纔會觸發一次,而且自帶節流功能。
  3. 判斷是否觸發了 media query
  4. 更新動畫而且發送事件
  5. 判斷是否有全屏操做事件
  6. 執行 requestAnimationFrame 回調
  7. 執行 IntersectionObserver 回調,該方法用於判斷元素是否可見,能夠用於懶加載上,可是兼容性很差
  8. 更新界面
  9. 以上就是一幀中可能會作的事情。若是在一幀中有空閒時間,就會去執行 requestIdleCallback 回調。

減小重繪和迴流

  • 使用 translate 替代 top
  • 使用 visibility 替換 display: none ,由於前者只會引發重繪,後者會引起迴流(改變了佈局)

  • 把 DOM 離線後修改,好比:先把 DOM 給 display:none (有一次 Reflow),而後你修改 100 次,而後再把它顯示出來

  • 不要把 DOM 結點的屬性值放在一個循環裏當成循環裏的變量

  • 不要使用 table 佈局,可能很小的一個小改動會形成整個 table 的從新佈局

  • 動畫實現的速度的選擇,動畫速度越快,迴流次數越多,也能夠選擇使用 requestAnimationFrame

  • CSS 選擇符從右往左匹配查找,避免 DOM 深度過深

  • 將頻繁運行的動畫變爲圖層,圖層可以阻止該節點回流影響別的元素。好比對於 video 標籤,瀏覽器會自動將該節點變爲圖層。

CSS

  • 避免使用table佈局。
  • 儘量在DOM樹的最末端改變class
  • 避免設置多層內聯樣式。
  • 將動畫效果應用到position屬性爲absolutefixed的元素上。
  • 避免使用CSS表達式(例如:calc())。

JavaScript

  • 避免頻繁操做樣式,最好一次性重寫style屬性,或者將樣式列表定義爲class並一次性更改class屬性。
  • 避免頻繁操做DOM,建立一個documentFragment,在它上面應用全部DOM操做,最後再把它添加到文檔中。
  • 也能夠先爲元素設置display: none,操做結束後再把它顯示出來。由於在display屬性爲none的元素上進行的DOM操做不會引起迴流和重繪。
  • 避免頻繁讀取會引起迴流/重繪的屬性,若是確實須要屢次使用,就用一個變量緩存起來。
  • 對具備複雜動畫的元素使用絕對定位,使它脫離文檔流,不然會引發父元素及後續元素頻繁迴流。

感謝及參考

整篇文章基本都是摘自下面文章,這裏表示感謝!

相關文章
相關標籤/搜索