本篇文章參考以下博文
迴流重繪比較
瀏覽器渲染 | 特點 | 消耗 | 常見操作 |
---|---|---|---|
重繪 | 頁面樣式的改變不影響佈局,只需要UI層面重新像素繪製 | 較小 | 改變元素顏色,改變背景色 |
迴流 | 瀏覽器重新渲染界面,需要重新佈局 | 較重 | 頁面初次渲染 窗口大小改變 元素尺寸/位置/內容發生變化 增加刪除可見元素 |
迴流必定會觸發重繪,重繪不一定會觸發迴流。
爲了提高頁面性能,其中一個思路就是減少瀏覽器的迴流,這個可以關聯到之前的兩篇文章,下面這兩個方法是減少迴流的經典案例。
瀏覽器渲染過程
回到正題,我們需要先了解一下瀏覽器的渲染過程。
- 首先瀏覽器向服務端發送請求,請求到了 html 文件和 css 文件。
- 然後分別解析兩個文件, html 解析成 Dom tree, css 解析成 cssom 樣式結構體。
- 然後 Dom tree 和 cssom 結合,產生 render tree。
這個 render tree 就是我們看到的頁面了。瞭解 React 或者 Vue 的同學應該不陌生,在這兩個框架中,當頁面變化的時候,會生成一個 Virtual Dom 然後根據 diff算法 來獲取其中變化的部分,替換變化的部分後,就形成了新的 render tree。 這也是一個經典的迴流過程。
如何減少迴流重繪
減少開銷,有一個核心思想, 能換就絕對不修,必須要修的時候拆下來修,而不是直接在手機上修,把各種 dom 操作,想象成修手機,攝像頭壞了,不修,直接拿個新的換上,屏幕壞了,不修,也直接拿個新的換上,主板壞了,必須要修了,先把主板卸下來,修好之後再安回去。
① 需要修改某些樣式的時候,不是直接獲取元素,然後修改樣式,而是直接給元素換一個 class 。
el.className += " className1";
② 使用 cssText 修改樣式
el.style.cssText += `; left: ${left} px; top: ${top} px;`;
③ 先讓元素脫離 render tree 修改好之後,再添加回去。只有兩次迴流
el.style.display = 'none'; //一次迴流
...//各種操作
el.style.display = 'block'; //兩次迴流
④ 當多次使用 offsetWidth 和 offsetHeight 等屬性的時候(offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight、getComputedStyle() )先讀取到變量中進行緩存。